Skip to content
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

Fixes and improvements for usability. #78

Merged
merged 5 commits into from
Nov 20, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,12 @@ import sbt.Keys.{name, mappings, sourceDirectory}
import linux.LinuxSymlink
import linux.LinuxPackageMapping

object GenericPackageSettings {
val installLocation = "/usr/share"
}
trait GenericPackageSettings
extends linux.LinuxPlugin
with debian.DebianPlugin
with rpm.RpmPlugin
with windows.WindowsPlugin
with universal.UniversalPlugin {
import GenericPackageSettings._

// This method wires a lot of hand-coded generalities about how to map directories
// into linux, and the conventions we expect.
Expand All @@ -33,6 +29,8 @@ trait GenericPackageSettings
* `<universal>/conf` directory is given a symlink to `/etc/<package-name>`
* Files in `conf/` or `etc/` directories are automatically marked as configuration.
* `../man/...1` files are automatically compressed into .gz files.
*
* TODO - We need to figure out how to handle ownership here.
*/
def mapGenericMappingsToLinux(mappings: Seq[(File, String)])(rename: String => String): Seq[LinuxPackageMapping] = {
val (directories, nondirectories) = mappings.partition(_._1.isDirectory)
Expand Down Expand Up @@ -62,12 +60,16 @@ trait GenericPackageSettings
}

def mapGenericFilesToLinux: Seq[Setting[_]] = Seq(

// Default place to install code.
defaultLinuxInstallLocation := "/usr/share",

// First we look at the src/linux files
linuxPackageMappings <++= (sourceDirectory in Linux) map { dir =>
mapGenericMappingsToLinux((dir.*** --- dir) x relativeTo(dir))(identity)
},
// Now we look at the src/universal files.
linuxPackageMappings <++= (normalizedName in Universal, mappings in Universal) map { (pkg, mappings) =>
linuxPackageMappings <++= (normalizedName in Universal, mappings in Universal, defaultLinuxInstallLocation) map { (pkg, mappings, installLocation) =>
// TODO - More windows filters...
def isWindowsFile(f: (File, String)): Boolean =
f._2 endsWith ".bat"
Expand All @@ -77,7 +79,7 @@ trait GenericPackageSettings
}
},
// Now we generate symlinks.
linuxPackageSymlinks <++= (normalizedName in Universal, mappings in Universal) map { (pkg, mappings) =>
linuxPackageSymlinks <++= (normalizedName in Universal, mappings in Universal, defaultLinuxInstallLocation) map { (pkg, mappings, installLocation) =>
for {
(file, name) <- mappings
if !file.isDirectory
Expand All @@ -86,7 +88,7 @@ trait GenericPackageSettings
} yield LinuxSymlink("/usr/" + name, installLocation+"/"+pkg+"/"+name)
},
// Map configuration files
linuxPackageSymlinks <++= (normalizedName in Universal, mappings in Universal) map { (pkg, mappings) =>
linuxPackageSymlinks <++= (normalizedName in Universal, mappings in Universal, defaultLinuxInstallLocation) map { (pkg, mappings, installLocation) =>
val needsConfLink =
mappings exists { case (file, name) =>
(name startsWith "conf/") && !file.isDirectory
Expand Down
3 changes: 2 additions & 1 deletion src/main/scala/com/typesafe/sbt/packager/Keys.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ object Keys extends linux.Keys
// TODO - Do these keys belong here?
def normalizedName = sbt.Keys.normalizedName

// These keys are used by the JavaApp archetype.
// These keys are used by the JavaApp/JavaServer archetypes.
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.")
Expand All @@ -28,4 +28,5 @@ object Keys extends linux.Keys
| APP_NAME - the name of the app
| APP_DEFINES - the defines to go into the app
| """.stripMargin)
val defaultLinuxInstallLocation = SettingKey[String]("defaultLinuxInstallLocation", "The location where we will install generic linux packages.")
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ object JavaServerAppPackaging {

def debianUpstartSettings: Seq[Setting[_]] =
Seq(
debianUpstartScriptReplacements <<= (maintainer in Debian, packageSummary in Debian, normalizedName, sbt.Keys.version) map { (author, descr, name, version) =>
debianUpstartScriptReplacements <<= (maintainer in Debian, packageSummary in Debian, normalizedName, sbt.Keys.version, defaultLinuxInstallLocation) map { (author, descr, name, version, installLocation) =>
// TODO name-version is copied from UniversalPlugin. This should be consolidated into a setting (install location...)
val chdir = GenericPackageSettings.installLocation + "/" + name + "/bin"
val chdir = installLocation + "/" + name + "/bin"
JavaAppUpstartScript.makeReplacements(author = author, descr = descr, execScript = name, chdir = chdir)
},
debianMakeUpstartScript <<= (debianUpstartScriptReplacements, normalizedName, target in Universal) map makeDebianUpstartScript,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,16 +111,6 @@ trait DebianPlugin extends Plugin with linux.LinuxPlugin {
chmod(cfile, "0644")
cfile
},
/*debianLinksfile <<= (name, linuxPackageSymlinks, target) map { (name, symlinks, dir) =>
val lfile = dir / "DEBIAN" / (name + ".links")
val content =
for {
LinuxSymlink(link, destination) <- symlinks
} yield link + " " + destination
IO.writeLines(lfile, content)
chmod(lfile, "0644")
lfile
},*/
debianExplodedPackage <<= (linuxPackageMappings, debianControlFile, debianMaintainerScripts, debianConffilesFile, debianControlScriptsReplacements, linuxPackageSymlinks, target)
map { (mappings, _, maintScripts, _, replacements, symlinks, t) =>

Expand Down Expand Up @@ -162,7 +152,7 @@ trait DebianPlugin extends Plugin with linux.LinuxPlugin {
if file.isFile
if !(name startsWith "DEBIAN")
if !(name contains "debian-binary")
// TODO - detect symlinks...
// TODO - detect symlinks with Java7 (when we can) rather than hackery...
if file.getCanonicalPath == file.getAbsolutePath
fixedName = if (name startsWith "/") name drop 1 else name
} yield Hashing.md5Sum(file) + " " + fixedName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ trait LinuxPlugin extends Plugin {
* @param dir - use some directory, e.g. target.value
* @param files
*/
def packageTemplateMapping(dir: File, files: String*) = LinuxPackageMapping(files map ((dir, _)))
def packageTemplateMapping(files: String*)(dir: File = new File(sys.props("java.io.tmpdir"))) = LinuxPackageMapping(files map ((dir, _)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks a lot better :)


// TODO - we'd like a set of conventions to take universal mappings and create linux package mappings.

Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/com/typesafe/sbt/packager/rpm/RpmHelper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,6 @@ object RpmHelper {
}
}

def evalMacro(macro: String): String =
Process(Seq("rpm", "--eval", '%' + macro)) !!
def evalMacro(mcro: String): String =
Process(Seq("rpm", "--eval", '%' + mcro)).!!
}
29 changes: 28 additions & 1 deletion src/main/scala/com/typesafe/sbt/packager/rpm/RpmMetadata.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ case class RpmMetadata(
case class RpmDescription(
license: Option[String] = None,
distribution: Option[String] = None,
//vendor: Option[String] = None,
url: Option[String] = None,
group: Option[String] = None,
packager: Option[String] = None,
Expand Down Expand Up @@ -75,6 +74,34 @@ case class RpmSpec(meta: RpmMetadata,
mappings: Seq[LinuxPackageMapping] = Seq.empty,
symlinks: Seq[LinuxSymlink] = Seq.empty) {


// TODO - here we want to validate that all the data we have is ok to place
// in the RPM. e.g. the Description/vendor etc. must meet specific requirements.
// For now we just check existence.
def validate(log: Logger): Unit = {
def ensureOr[T](value: T, msg: String, validator: T => Boolean): Boolean = {
if(validator(value)) true
else {
log.error(msg)
false
}
}
def isNonEmpty(s: String): Boolean = !s.isEmpty
val emptyValidators =
Seq(
ensureOr(meta.name, "`name in Rpm` is empty. Please provide one.", isNonEmpty),
ensureOr(meta.version, "`version in Rpm` is empty. Please provide a vaid version for the rpm SPEC.", isNonEmpty),
ensureOr(meta.release, "`rpmRelease in Rpm` is empty. Please provide a valid release number for the rpm SPEC.", isNonEmpty),
ensureOr(meta.arch, "`packageArchitecture in Rpm` is empty. Please provide a valid archiecture for the rpm SPEC.", isNonEmpty),
ensureOr(meta.vendor, "`rpmVendor in Rpm` is empty. Please provide a valid vendor for the rpm SPEC.", isNonEmpty),
ensureOr(meta.os, "`rpmOs in Rpm` is empty. Please provide a valid os vaue for the rpm SPEC.", isNonEmpty),
ensureOr(meta.summary, "`packageSummary in Rpm` is empty. Please provide a valid summary for the rpm SPEC.", isNonEmpty),
ensureOr(meta.description, "`packageDescription in Rpm` is empty. Please provide a valid description for the rpm SPEC.", isNonEmpty)
)
// TODO - Continue validating after this point?
if(!emptyValidators.forall(identity)) sys.error("There are issues with the rpm spec data.")
}

private[this] def fixFilename(n: String): String = {
val tmp =
if(n startsWith "/") n
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ trait RpmPlugin extends Plugin with LinuxPlugin {
rpmSpecConfig <<=
(rpmMetadata, rpmDescription, rpmDependencies, rpmScripts, linuxPackageMappings, linuxPackageSymlinks) map RpmSpec,
packageBin <<= (rpmSpecConfig, target, streams) map { (spec, dir, s) =>
spec.validate(s.log)
RpmHelper.buildRpm(spec, dir, s.log)
},
rpmLint <<= (packageBin, streams) map { (rpm, s) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ object ZipHelper {
}

/** Creates a zip file attempting to give files the appropriate unix permissions using Java 6 APIs.
* Note: This is known to have some odd issues on MacOSX whereby executable permissions
* are not actually discovered, even though the Info-Zip headers exist and work on
* many variants of linux. Yay Apple.
* @param sources The files to include in the zip file.
* @param outputZip The location of the output file.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ object WixHelper {
</Component>
</DirectoryRef>
ComponentInfo(id, xml)
// TODO - To have shortcuts, you MUST put something in the registry. Here,
// We should have shortcuts actually provide us with what they want in the registry,
// rather than forcing it to be something.
// Also, we need some mechanism to ensure the start menu folder is removed in the event
// that we remove all menu items.
case AddShortCuts(targets, workingDir) =>
val id = cleanStringForId("shortcut_" + makeGUID).takeRight(67) // Room for "_SC"
val xml =
Expand Down