-
Notifications
You must be signed in to change notification settings - Fork 37
add startScriptArgs setting #43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,6 +24,7 @@ object SbtStartScript extends Plugin { | |
|
|
||
| object StartScriptKeys { | ||
| val startScriptFile = SettingKey[File]("start-script-name") | ||
| val startScriptArgs = SettingKey[Seq[String]]("start-script-args", "arguments to be prepended to the command line arguments to the main class") | ||
| // this is newly-added to make the val name consistent with the | ||
| // string name, and preferred over startScriptFile | ||
| val startScriptName = startScriptFile | ||
|
|
@@ -62,6 +63,7 @@ object SbtStartScript extends Plugin { | |
| // these settings to any project. | ||
| val genericStartScriptSettings: Seq[Project.Setting[_]] = Seq( | ||
| startScriptFile <<= (target) { (target) => target / scriptname }, | ||
| startScriptArgs := Seq(), | ||
| // maybe not the right way to do this... | ||
| startScriptBaseDirectory <<= (thisProjectRef) { (ref) => new File(ref.build) }, | ||
| startScriptNotDefined in Compile <<= (streams, startScriptFile in Compile) map startScriptNotDefinedTask, | ||
|
|
@@ -77,17 +79,17 @@ object SbtStartScript extends Plugin { | |
| startScriptJettyURL in Compile <<= (startScriptJettyVersion in Compile) { (version) => "http://archive.eclipse.org/jetty/" + version + "/dist/jetty-distribution-" + version + ".zip" }, | ||
| startScriptJettyContextPath in Compile := "/", | ||
| startScriptJettyHome in Compile <<= (streams, target, startScriptJettyURL in Compile, startScriptJettyChecksum in Compile) map startScriptJettyHomeTask, | ||
| startScriptForWar in Compile <<= (streams, startScriptBaseDirectory, startScriptFile in Compile, packageWar in Compile, startScriptJettyHome in Compile, startScriptJettyContextPath in Compile) map startScriptForWarTask, | ||
| startScriptForWar in Compile <<= (streams, startScriptBaseDirectory, startScriptFile in Compile, packageWar in Compile, startScriptJettyHome in Compile, startScriptJettyContextPath in Compile, startScriptArgs in Compile) map startScriptForWarTask, | ||
| startScript in Compile <<= startScriptForWar in Compile) ++ genericStartScriptSettings | ||
|
|
||
| // settings to be added to a project with an exported jar | ||
| val startScriptForJarSettings: Seq[Project.Setting[_]] = Seq( | ||
| startScriptForJar in Compile <<= (streams, startScriptBaseDirectory, startScriptFile in Compile, packageBin in Compile, relativeDependencyClasspathString in Compile, mainClass in Compile) map startScriptForJarTask, | ||
| startScriptForJar in Compile <<= (streams, startScriptBaseDirectory, startScriptFile in Compile, packageBin in Compile, relativeDependencyClasspathString in Compile, mainClass in Compile, startScriptArgs in Compile) map startScriptForJarTask, | ||
| startScript in Compile <<= startScriptForJar in Compile) ++ genericStartScriptSettings | ||
|
|
||
| // settings to be added to a project that doesn't export a jar | ||
| val startScriptForClassesSettings: Seq[Project.Setting[_]] = Seq( | ||
| startScriptForClasses in Compile <<= (streams, startScriptBaseDirectory, startScriptFile in Compile, relativeFullClasspathString in Compile, mainClass in Compile) map startScriptForClassesTask, | ||
| startScriptForClasses in Compile <<= (streams, startScriptBaseDirectory, startScriptFile in Compile, relativeFullClasspathString in Compile, mainClass in Compile, startScriptArgs in Compile) map startScriptForClassesTask, | ||
| startScript in Compile <<= startScriptForClasses in Compile) ++ genericStartScriptSettings | ||
|
|
||
| // Extracted.getOpt is not in 10.1 and earlier | ||
|
|
@@ -305,26 +307,27 @@ fi | |
| scriptFile.setExecutable(true) | ||
| } | ||
|
|
||
| def startScriptForClassesTask(streams: TaskStreams, baseDirectory: File, scriptFile: File, cpString: RelativeClasspathString, maybeMainClass: Option[String]) = { | ||
| def startScriptForClassesTask(streams: TaskStreams, baseDirectory: File, scriptFile: File, cpString: RelativeClasspathString, maybeMainClass: Option[String], args: Seq[String]) = { | ||
| val templateWindows = """@echo off | ||
| @SCRIPT_ROOT_DETECT@ | ||
|
|
||
| @MAIN_CLASS_SETUP@ | ||
|
|
||
| java %JOPTS% -cp "@CLASSPATH@" "%MAINCLASS%" %* | ||
| java %JOPTS% -cp "@CLASSPATH@" "%MAINCLASS%" @ARGS@ %* | ||
|
|
||
| """ | ||
| val templateLinux = """#!/bin/bash | ||
| @SCRIPT_ROOT_DETECT@ | ||
|
|
||
| @MAIN_CLASS_SETUP@ | ||
|
|
||
| exec java $JAVA_OPTS -cp "@CLASSPATH@" "$MAINCLASS" "$@" | ||
| exec java $JAVA_OPTS -cp "@CLASSPATH@" "$MAINCLASS" @ARGS@ "$@" | ||
|
|
||
| """ | ||
| val template: String = if (isWindows()) templateWindows else templateLinux | ||
| val script = renderTemplate(template, Map("SCRIPT_ROOT_DETECT" -> scriptRootDetect(baseDirectory, scriptFile, None), | ||
| "CLASSPATH" -> cpString.value, | ||
| "ARGS" -> args.map(x => "\"" + x + "\"").mkString, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. on unix the easiest way to quote is single quotes; something like this: i.e. put all single quotes outside of single quotes and backslash them, single quote everything else. Double quotes are hard to get right because they support backslash escapes and On Windows, who knows. I guess we have been just adding double quotes so far.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No matter what we do, we’d have to document it, and people would need to be aware of how exactly it works; there is no path we can take which Just Works. In this light I propose to just document that no translation is done whatsoever apart from surrounding it with double quotes. Then the user has full control over what goes on in the script. (reflection: the goal could be that strings can be passed literally from the build definition into the main method’s argument array, but is that really achievable?)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd propose either no translation (no double quotes) and say that people have to quote it themselves in platform-aware fashion; or quote correctly for the two platforms. Surrounding with double quotes and nothing else is pretty much just wrong, since it won't handle I know on unix it is correct to replace all single quotes in the original string with close single, backslash-single, and open single. Then put single quotes around the outside. So we may as well do that instead of something broken with double quotes. I don't really know what to do on Windows but we could leave the double quotes around the outside and let someone send a patch to improve it, I suppose.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, I see your point; I cannot test the Windows part myself, though. Will amend for Linux only. |
||
| "MAIN_CLASS_SETUP" -> mainClassSetup(maybeMainClass))) | ||
| writeScript(scriptFile, script) | ||
| streams.log.info("Wrote start script for mainClass := " + maybeMainClass + " to " + scriptFile) | ||
|
|
@@ -337,28 +340,29 @@ exec java $JAVA_OPTS -cp "@CLASSPATH@" "$MAINCLASS" "$@" | |
| // We put jar on the classpath and supply a mainClass because with "java -jar" | ||
| // the deps have to be bundled in the jar (classpath is ignored), and SBT does | ||
| // not normally do that. | ||
| def startScriptForJarTask(streams: TaskStreams, baseDirectory: File, scriptFile: File, jarFile: File, cpString: RelativeClasspathString, maybeMainClass: Option[String]) = { | ||
| def startScriptForJarTask(streams: TaskStreams, baseDirectory: File, scriptFile: File, jarFile: File, cpString: RelativeClasspathString, maybeMainClass: Option[String], args: Seq[String]) = { | ||
| val templateWindows = """@echo off | ||
| @SCRIPT_ROOT_DETECT@ | ||
|
|
||
| @MAIN_CLASS_SETUP@ | ||
|
|
||
| java %JOPTS% -cp "@CLASSPATH@" %MAINCLASS% %* | ||
| java %JOPTS% -cp "@CLASSPATH@" %MAINCLASS% @ARGS@ %* | ||
|
|
||
| """ | ||
| val templateLinux = """#!/bin/bash | ||
| @SCRIPT_ROOT_DETECT@ | ||
|
|
||
| @MAIN_CLASS_SETUP@ | ||
|
|
||
| exec java $JAVA_OPTS -cp "@CLASSPATH@" "$MAINCLASS" "$@" | ||
| exec java $JAVA_OPTS -cp "@CLASSPATH@" "$MAINCLASS" @ARGS@ "$@" | ||
|
|
||
| """ | ||
| val template: String = if (isWindows()) templateWindows else templateLinux | ||
| val relativeJarFile = relativizeFile(baseDirectory, jarFile) | ||
|
|
||
| val script = renderTemplate(template, Map("SCRIPT_ROOT_DETECT" -> scriptRootDetect(baseDirectory, scriptFile, Some(relativeJarFile)), | ||
| "CLASSPATH" -> cpString.value, | ||
| "ARGS" -> args.map(x => "\"" + x + "\"").mkString, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. might be good to factor this args-to-string thing out especially if making it any more complicated
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, good point |
||
| "MAIN_CLASS_SETUP" -> mainClassSetup(maybeMainClass))) | ||
| writeScript(scriptFile, script) | ||
| streams.log.info("Wrote start script for jar " + relativeJarFile + " to " + scriptFile + " with mainClass := " + maybeMainClass) | ||
|
|
@@ -369,7 +373,7 @@ exec java $JAVA_OPTS -cp "@CLASSPATH@" "$MAINCLASS" "$@" | |
| // we need to download and unpack the Jetty "distribution" which isn't | ||
| // a normal jar dependency. Not sure if Ivy can do that, may have to just | ||
| // have a configurable URL and checksum. | ||
| def startScriptForWarTask(streams: TaskStreams, baseDirectory: File, scriptFile: File, warFile: File, jettyHome: File, jettyContextPath: String) = { | ||
| def startScriptForWarTask(streams: TaskStreams, baseDirectory: File, scriptFile: File, warFile: File, jettyHome: File, jettyContextPath: String, args: Seq[String]) = { | ||
|
|
||
| // First we need a Jetty config to move us to the right context path | ||
| val contextFile = jettyHome / "contexts" / "start-script.xml" | ||
|
|
@@ -394,7 +398,7 @@ copy "@WARFILE@" "@JETTY_HOME@\webapps" || (echo "Failed to copy @WARFILE@ to @J | |
|
|
||
| if "%PORT%"=="" (set PORT=8080) | ||
|
|
||
| java %JAVA_OPTS% -Djetty.port="%PORT%" -Djetty.home="@JETTY_HOME@" -jar "@JETTY_HOME@\start.jar" %* | ||
| java %JAVA_OPTS% -Djetty.port="%PORT%" -Djetty.home="@JETTY_HOME@" -jar "@JETTY_HOME@\start.jar" @ARGS@ %* | ||
|
|
||
| """ | ||
| val templateLinux = """#!/bin/bash | ||
|
|
@@ -406,7 +410,7 @@ if test x"$PORT" = x ; then | |
| PORT=8080 | ||
| fi | ||
|
|
||
| exec java $JAVA_OPTS -Djetty.port="$PORT" -Djetty.home="@JETTY_HOME@" -jar "@JETTY_HOME@/start.jar" "$@" | ||
| exec java $JAVA_OPTS -Djetty.port="$PORT" -Djetty.home="@JETTY_HOME@" -jar "@JETTY_HOME@/start.jar" @ARGS@ "$@" | ||
|
|
||
| """ | ||
| val template: String = if (isWindows()) templateWindows else templateLinux | ||
|
|
@@ -415,6 +419,7 @@ exec java $JAVA_OPTS -Djetty.port="$PORT" -Djetty.home="@JETTY_HOME@" -jar "@JET | |
| val script = renderTemplate(template, | ||
| Map("SCRIPT_ROOT_DETECT" -> scriptRootDetect(baseDirectory, scriptFile, Some(relativeWarFile)), | ||
| "WARFILE" -> relativeWarFile.toString, | ||
| "ARGS" -> args.map(x => "\"" + x + "\"").mkString, | ||
| "JETTY_HOME" -> jettyHome.toString)) | ||
| writeScript(scriptFile, script) | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since the args are passed through as-is (no quoting), people would have to do any quoting themselves, and separately for linux/mac and windows - should we auto-quote each arg for them? I know how to do that for unix but not Windows. The way we are doing classpath is bogus and doesn't handle backslashes or double quotes in the classpath, though we've gotten away with it so far.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh just saw below that you are doing double quotes