Skip to content

Commit

Permalink
Merge pull request #121 from sbt/wip/overridable-script-templates
Browse files Browse the repository at this point in the history
Allow script templates to be overridden
  • Loading branch information
jsuereth committed Jan 6, 2014
2 parents d9b49e7 + bc0ed11 commit c36cc8e
Show file tree
Hide file tree
Showing 11 changed files with 206 additions and 50 deletions.
1 change: 1 addition & 0 deletions src/main/scala/com/typesafe/sbt/packager/Keys.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ object Keys extends linux.Keys
val makeBashScript = TaskKey[Option[File]]("makeBashScript", "Creates or discovers the bash script used by this project.")
val bashScriptDefines = TaskKey[Seq[String]]("bashScriptDefines", "A list of definitions that should be written to the bash file template.")
val bashScriptExtraDefines = TaskKey[Seq[String]]("bashScriptExtraDefines", "A list of extra definitions that should be written to the bash file template.")
val bashScriptConfigLocation = TaskKey[Option[String]]("bashScriptConfigLocation", "The location where the bash script will load default argument configuration from.")
val batScriptExtraDefines = TaskKey[Seq[String]]("batScriptExtraDefines", "A list of extra definitions that should be written to the bat file template.")
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.")
Expand Down
26 changes: 17 additions & 9 deletions src/main/scala/com/typesafe/sbt/packager/archetypes/JavaApp.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package archetypes
import Keys._
import sbt._
import sbt.Project.Initialize
import sbt.Keys.{ mappings, target, name, mainClass, normalizedName }
import sbt.Keys.{ mappings, target, name, mainClass, normalizedName, sourceDirectory }
import linux.LinuxPackageMapping
import SbtNativePackager._

Expand Down Expand Up @@ -36,22 +36,24 @@ object JavaAppPackaging {
mappings in Universal <++= scriptClasspathOrdering,
scriptClasspath <<= scriptClasspathOrdering map makeRelativeClasspathNames,
bashScriptExtraDefines := Nil,
bashScriptDefines <<= (Keys.mainClass in Compile, scriptClasspath, bashScriptExtraDefines) map { (mainClass, cp, extras) =>
bashScriptConfigLocation <<= bashScriptConfigLocation ?? None,
bashScriptDefines <<= (Keys.mainClass in Compile, scriptClasspath, bashScriptExtraDefines, bashScriptConfigLocation) map { (mainClass, cp, extras, config) =>
val hasMain =
for {
cn <- mainClass
} yield JavaAppBashScript.makeDefines(cn, appClasspath = cp, extras = extras)
} yield JavaAppBashScript.makeDefines(cn, appClasspath = cp, extras = extras, configFile = config)
hasMain getOrElse Nil
},
makeBashScript <<= (bashScriptDefines, target in Universal, normalizedName) map makeUniversalBinScript,
// TODO - Overridable bash template.
makeBashScript <<= (bashScriptDefines, target in Universal, normalizedName, sourceDirectory) map makeUniversalBinScript,
batScriptExtraDefines := Nil,
batScriptReplacements <<= (normalizedName, Keys.mainClass in Compile, scriptClasspath, batScriptExtraDefines) map { (name, mainClass, cp, extras) =>
mainClass map { mc =>
JavaAppBatScript.makeReplacements(name = name, mainClass = mc, appClasspath = cp, extras = extras)
} getOrElse Nil

},
makeBatScript <<= (batScriptReplacements, target in Universal, normalizedName) map makeUniversalBatScript,
makeBatScript <<= (batScriptReplacements, target in Universal, normalizedName, sourceDirectory) map makeUniversalBatScript,
mappings in Universal <++= (makeBashScript, normalizedName) map { (script, name) =>
for {
s <- script.toSeq
Expand All @@ -73,21 +75,27 @@ object JavaAppPackaging {
else "../" + name
}

def makeUniversalBinScript(defines: Seq[String], tmpDir: File, name: String): Option[File] =
def makeUniversalBinScript(defines: Seq[String], tmpDir: File, name: String, sourceDir: File): Option[File] =
if (defines.isEmpty) None
else {
val scriptBits = JavaAppBashScript.generateScript(defines)
val defaultTemplateLocation = sourceDir / "templates" / "bash-template"
val scriptBits =
if(defaultTemplateLocation.exists) JavaAppBashScript.generateScript(defines, defaultTemplateLocation.toURI.toURL)
else JavaAppBashScript.generateScript(defines)
val script = tmpDir / "tmp" / "bin" / name
IO.write(script, scriptBits)
// TODO - Better control over this!
script.setExecutable(true)
Some(script)
}

def makeUniversalBatScript(replacements: Seq[(String, String)], tmpDir: File, name: String): Option[File] =
def makeUniversalBatScript(replacements: Seq[(String, String)], tmpDir: File, name: String, sourceDir: File): Option[File] =
if (replacements.isEmpty) None
else {
val scriptBits = JavaAppBatScript.generateScript(replacements)
val defaultTemplateLocation = sourceDir / "templates" / "bat-template"
val scriptBits =
if(defaultTemplateLocation.exists) JavaAppBatScript.generateScript(replacements, defaultTemplateLocation.toURI.toURL)
else JavaAppBatScript.generateScript(replacements)
val script = tmpDir / "tmp" / "bin" / (name + ".bat")
IO.write(script, scriptBits)
Some(script)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.typesafe.sbt.packager.archetypes

import java.net.URL

/**
* Constructs a bash script for running a java application.
*
Expand Down Expand Up @@ -33,10 +35,10 @@ object JavaAppBashScript {
val fullString = cp map (n => "$lib_dir/"+n) mkString ":"
"declare -r app_classpath=\""+fullString+"\"\n"
}
def generateScript(defines: Seq[String]): String = {
def generateScript(defines: Seq[String], template: URL = bashTemplateSource): String = {
val defineString = defines mkString "\n"
val replacements = Seq("template_declares" -> defineString)
TemplateWriter.generateScript(bashTemplateSource, replacements)
TemplateWriter.generateScript(template, replacements)
}

def configFileDefine(configFile: String) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ object JavaAppBatScript {
}

def generateScript(
replacements: Seq[(String,String)]): String =
TemplateWriter.generateScript(bashTemplateSource, replacements, "\r\n", TemplateWriter.batFriendlyKeySurround)
replacements: Seq[(String,String)], template: java.net.URL = bashTemplateSource): String =
TemplateWriter.generateScript(template, replacements, "\r\n", TemplateWriter.batFriendlyKeySurround)

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.typesafe.sbt.packager.archetypes

import java.io.File
import java.net.URL

/**
* Constructs an start script for running a java application.
*
Expand All @@ -8,31 +11,32 @@ object JavaAppStartScript {

import ServerLoader._

protected def upstartTemplateSource: java.net.URL = getClass.getResource("upstart-template")
protected def sysvinitTemplateSource: java.net.URL = getClass.getResource("sysvinit-template")
protected def postinstTemplateSource: java.net.URL = getClass.getResource("postinst-template")
protected def postinstSysvinitTemplateSource: java.net.URL = getClass.getResource("postinst-sysvinit-template")
protected def preremTemplateSource: java.net.URL = getClass.getResource("prerem-template")


def generateScript(replacements: Seq[(String, String)], loader: ServerLoader): String =
loader match {
case Upstart =>
TemplateWriter.generateScript(upstartTemplateSource, replacements)
case SystemV =>
TemplateWriter.generateScript(sysvinitTemplateSource, replacements)
protected def upstartTemplateSource: URL = getClass.getResource("upstart-template")
protected def sysvinitTemplateSource: URL = getClass.getResource("sysvinit-template")
protected def postinstTemplateSource: URL = getClass.getResource("postinst-template")
protected def postinstSysvinitTemplateSource: URL = getClass.getResource("postinst-sysvinit-template")
protected def preremTemplateSource: URL = getClass.getResource("prerem-template")


def defaultStartScriptTemplate(loader: ServerLoader, defaultLocation: File): URL =
if(defaultLocation.exists) defaultLocation.toURI.toURL
else loader match {
case Upstart => upstartTemplateSource
case SystemV => sysvinitTemplateSource
}


def generatePrerm(appName: String): String =
TemplateWriter.generateScript(preremTemplateSource, Seq("app_name" -> appName))
def generatePrerm(appName: String, template: java.net.URL = preremTemplateSource): String =
TemplateWriter.generateScript(template, Seq("app_name" -> appName))


def generatePostinst(appName: String, loader: ServerLoader): String =
loader match {
case Upstart =>
def generatePostinst(appName: String, loader: ServerLoader, template: Option[java.net.URL] = None): String =
(template, loader) match {
// User has overriden the default.
case (Some(template), _) => TemplateWriter.generateScript(template, Seq("app_name" -> appName))
case (_, Upstart) =>
TemplateWriter.generateScript(postinstTemplateSource, Seq("app_name" -> appName))
case SystemV =>
case (_, SystemV) =>
TemplateWriter.generateScript(postinstSysvinitTemplateSource, Seq("app_name" -> appName))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package archetypes

import Keys._
import sbt._
import sbt.Keys.{ target, mainClass, normalizedName }
import sbt.Keys.{ target, mainClass, normalizedName, sourceDirectory }
import SbtNativePackager._
import com.typesafe.sbt.packager.linux.{ LinuxFileMetaData, LinuxPackageMapping, LinuxSymlink, LinuxPlugin }

Expand All @@ -28,6 +28,7 @@ object JavaServerAppPackaging {
Seq(
serverLoading := Upstart,
daemonUser := Users.Root,
// This one is begging for sbt 0.13 syntax...
debianStartScriptReplacements <<= (
maintainer in Debian, packageSummary in Debian, serverLoading in Debian, daemonUser in Debian, normalizedName,
sbt.Keys.version, defaultLinuxInstallLocation, mainClass in Compile, scriptClasspath)
Expand All @@ -45,9 +46,18 @@ object JavaServerAppPackaging {
appMainClass = mainClass.get,
daemonUser = daemonUser)
},
debianMakeStartScript <<= (debianStartScriptReplacements, normalizedName, target in Universal, serverLoading in Debian)
// TODO - Default locations shouldn't be so hacky.
linuxStartScriptTemplate in Debian <<= (serverLoading in Debian, sourceDirectory) map { (loader, dir) =>
JavaAppStartScript.defaultStartScriptTemplate(loader, dir / "templates" / "start")
},
debianMakeStartScript <<= (debianStartScriptReplacements, normalizedName, target in Universal, linuxStartScriptTemplate in Debian)
map makeDebianStartScript,
debianMakeEtcDefault <<= (normalizedName, target in Universal, serverLoading in Debian)
linuxEtcDefaultTemplate in Debian <<= sourceDirectory map { dir =>
val overrideScript = dir / "templates" / "etc-default"
if(overrideScript.exists) overrideScript.toURI.toURL
else etcDefaultTemplateSource
},
debianMakeEtcDefault <<= (normalizedName, target in Universal, serverLoading in Debian, linuxEtcDefaultTemplate in Debian)
map makeEtcDefaultScript,
linuxPackageMappings in Debian <++= (debianMakeEtcDefault, normalizedName) map { (conf, name) =>
conf.map(c => LinuxPackageMapping(Seq(c -> ("/etc/default/" + name))).withConfig()).toSeq
Expand All @@ -58,7 +68,6 @@ object JavaServerAppPackaging {
case Upstart => ("/etc/init/" + name + ".conf", "0644")
case SystemV => ("/etc/init.d/" + name, "0755")
}

for {
s <- script.toSeq
} yield LinuxPackageMapping(Seq(s -> path)).withPerms(permissions)
Expand All @@ -79,10 +88,10 @@ object JavaServerAppPackaging {
debianMakePostinstScript <<= (normalizedName, target in Universal, serverLoading in Debian) map makeDebianPostinstScript)

private def makeDebianStartScript(
replacements: Seq[(String, String)], name: String, tmpDir: File, loader: ServerLoader): Option[File] =
replacements: Seq[(String, String)], name: String, tmpDir: File, template: URL): Option[File] =
if (replacements.isEmpty) None
else {
val scriptBits = JavaAppStartScript.generateScript(replacements, loader)
val scriptBits = TemplateWriter.generateScript(template, replacements)
val script = tmpDir / "tmp" / "init" / name
IO.write(script, scriptBits)
Some(script)
Expand All @@ -102,11 +111,11 @@ object JavaServerAppPackaging {
Some(script)
}

protected def makeEtcDefaultScript(name: String, tmpDir: File, loader: ServerLoader): Option[File] = {
protected def makeEtcDefaultScript(name: String, tmpDir: File, loader: ServerLoader, source: java.net.URL): Option[File] = {
loader match {
case Upstart => None
case SystemV => {
val scriptBits = TemplateWriter.generateScript(etcDefaultTemplateSource, Seq.empty)
val scriptBits = TemplateWriter.generateScript(source, Seq.empty)
val script = tmpDir / "tmp" / "etc" / "default" / name
IO.write(script, scriptBits)
Some(script)
Expand Down
3 changes: 3 additions & 0 deletions src/main/scala/com/typesafe/sbt/packager/linux/Keys.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ trait Keys {
val linuxPackageMappings = TaskKey[Seq[LinuxPackageMapping]]("linux-package-mappings", "File to install location mappings including owner and privileges.")
val linuxPackageSymlinks = TaskKey[Seq[LinuxSymlink]]("linux-package-symlinks", "Symlinks we should produce in the underlying package.")
val generateManPages = TaskKey[Unit]("generate-man-pages", "Shows all the man files in the current project")

val linuxStartScriptTemplate = TaskKey[URL]("linuxStartScriptTemplate", "The location of the template start script file we use for debian (upstart or init.d")
val linuxEtcDefaultTemplate = TaskKey[URL]("linuxEtcDefaultTemplate", "The location of the /etc/default/<pkg> template script.")
}

object Keys extends Keys {
Expand Down
Loading

0 comments on commit c36cc8e

Please sign in to comment.