Skip to content

Commit f1cc833

Browse files
committed
Merge pull request #78 from sbt/configure-default-user-and-dir
Fixes and improvements for usability.
2 parents c00a692 + b8078a3 commit f1cc833

File tree

10 files changed

+54
-25
lines changed

10 files changed

+54
-25
lines changed

src/main/scala/com/typesafe/sbt/packager/GenericPackageSettings.scala

+9-7
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,12 @@ import sbt.Keys.{name, mappings, sourceDirectory}
77
import linux.LinuxSymlink
88
import linux.LinuxPackageMapping
99

10-
object GenericPackageSettings {
11-
val installLocation = "/usr/share"
12-
}
1310
trait GenericPackageSettings
1411
extends linux.LinuxPlugin
1512
with debian.DebianPlugin
1613
with rpm.RpmPlugin
1714
with windows.WindowsPlugin
1815
with universal.UniversalPlugin {
19-
import GenericPackageSettings._
2016

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

6462
def mapGenericFilesToLinux: Seq[Setting[_]] = Seq(
63+
64+
// Default place to install code.
65+
defaultLinuxInstallLocation := "/usr/share",
66+
6567
// First we look at the src/linux files
6668
linuxPackageMappings <++= (sourceDirectory in Linux) map { dir =>
6769
mapGenericMappingsToLinux((dir.*** --- dir) x relativeTo(dir))(identity)
6870
},
6971
// Now we look at the src/universal files.
70-
linuxPackageMappings <++= (normalizedName in Universal, mappings in Universal) map { (pkg, mappings) =>
72+
linuxPackageMappings <++= (normalizedName in Universal, mappings in Universal, defaultLinuxInstallLocation) map { (pkg, mappings, installLocation) =>
7173
// TODO - More windows filters...
7274
def isWindowsFile(f: (File, String)): Boolean =
7375
f._2 endsWith ".bat"
@@ -77,7 +79,7 @@ trait GenericPackageSettings
7779
}
7880
},
7981
// Now we generate symlinks.
80-
linuxPackageSymlinks <++= (normalizedName in Universal, mappings in Universal) map { (pkg, mappings) =>
82+
linuxPackageSymlinks <++= (normalizedName in Universal, mappings in Universal, defaultLinuxInstallLocation) map { (pkg, mappings, installLocation) =>
8183
for {
8284
(file, name) <- mappings
8385
if !file.isDirectory
@@ -86,7 +88,7 @@ trait GenericPackageSettings
8688
} yield LinuxSymlink("/usr/" + name, installLocation+"/"+pkg+"/"+name)
8789
},
8890
// Map configuration files
89-
linuxPackageSymlinks <++= (normalizedName in Universal, mappings in Universal) map { (pkg, mappings) =>
91+
linuxPackageSymlinks <++= (normalizedName in Universal, mappings in Universal, defaultLinuxInstallLocation) map { (pkg, mappings, installLocation) =>
9092
val needsConfLink =
9193
mappings exists { case (file, name) =>
9294
(name startsWith "conf/") && !file.isDirectory

src/main/scala/com/typesafe/sbt/packager/Keys.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ object Keys extends linux.Keys
1212
// TODO - Do these keys belong here?
1313
def normalizedName = sbt.Keys.normalizedName
1414

15-
// These keys are used by the JavaApp archetype.
15+
// These keys are used by the JavaApp/JavaServer archetypes.
1616
val makeBashScript = TaskKey[Option[File]]("makeBashScript", "Creates or discovers the bash script used by this project.")
1717
val bashScriptDefines = TaskKey[Seq[String]]("bashScriptDefines", "A list of definitions that should be written to the bash file template.")
1818
val bashScriptExtraDefines = TaskKey[Seq[String]]("bashScriptExtraDefines", "A list of extra definitions that should be written to the bash file template.")
@@ -28,4 +28,5 @@ object Keys extends linux.Keys
2828
| APP_NAME - the name of the app
2929
| APP_DEFINES - the defines to go into the app
3030
| """.stripMargin)
31+
val defaultLinuxInstallLocation = SettingKey[String]("defaultLinuxInstallLocation", "The location where we will install generic linux packages.")
3132
}

src/main/scala/com/typesafe/sbt/packager/archetypes/JavaServerApplication.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ object JavaServerAppPackaging {
2727

2828
def debianUpstartSettings: Seq[Setting[_]] =
2929
Seq(
30-
debianUpstartScriptReplacements <<= (maintainer in Debian, packageSummary in Debian, normalizedName, sbt.Keys.version) map { (author, descr, name, version) =>
30+
debianUpstartScriptReplacements <<= (maintainer in Debian, packageSummary in Debian, normalizedName, sbt.Keys.version, defaultLinuxInstallLocation) map { (author, descr, name, version, installLocation) =>
3131
// TODO name-version is copied from UniversalPlugin. This should be consolidated into a setting (install location...)
32-
val chdir = GenericPackageSettings.installLocation + "/" + name + "/bin"
32+
val chdir = installLocation + "/" + name + "/bin"
3333
JavaAppUpstartScript.makeReplacements(author = author, descr = descr, execScript = name, chdir = chdir)
3434
},
3535
debianMakeUpstartScript <<= (debianUpstartScriptReplacements, normalizedName, target in Universal) map makeDebianUpstartScript,

src/main/scala/com/typesafe/sbt/packager/debian/DebianPlugin.scala

+1-11
Original file line numberDiff line numberDiff line change
@@ -111,16 +111,6 @@ trait DebianPlugin extends Plugin with linux.LinuxPlugin {
111111
chmod(cfile, "0644")
112112
cfile
113113
},
114-
/*debianLinksfile <<= (name, linuxPackageSymlinks, target) map { (name, symlinks, dir) =>
115-
val lfile = dir / "DEBIAN" / (name + ".links")
116-
val content =
117-
for {
118-
LinuxSymlink(link, destination) <- symlinks
119-
} yield link + " " + destination
120-
IO.writeLines(lfile, content)
121-
chmod(lfile, "0644")
122-
lfile
123-
},*/
124114
debianExplodedPackage <<= (linuxPackageMappings, debianControlFile, debianMaintainerScripts, debianConffilesFile, debianControlScriptsReplacements, linuxPackageSymlinks, target)
125115
map { (mappings, _, maintScripts, _, replacements, symlinks, t) =>
126116

@@ -162,7 +152,7 @@ trait DebianPlugin extends Plugin with linux.LinuxPlugin {
162152
if file.isFile
163153
if !(name startsWith "DEBIAN")
164154
if !(name contains "debian-binary")
165-
// TODO - detect symlinks...
155+
// TODO - detect symlinks with Java7 (when we can) rather than hackery...
166156
if file.getCanonicalPath == file.getAbsolutePath
167157
fixedName = if (name startsWith "/") name drop 1 else name
168158
} yield Hashing.md5Sum(file) + " " + fixedName

src/main/scala/com/typesafe/sbt/packager/linux/LinuxPlugin.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ trait LinuxPlugin extends Plugin {
3434
* @param dir - use some directory, e.g. target.value
3535
* @param files
3636
*/
37-
def packageTemplateMapping(dir: File, files: String*) = LinuxPackageMapping(files map ((dir, _)))
37+
def packageTemplateMapping(files: String*)(dir: File = new File(sys.props("java.io.tmpdir"))) = LinuxPackageMapping(files map ((dir, _)))
3838

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

src/main/scala/com/typesafe/sbt/packager/rpm/RpmHelper.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,6 @@ object RpmHelper {
102102
}
103103
}
104104

105-
def evalMacro(macro: String): String =
106-
Process(Seq("rpm", "--eval", '%' + macro)) !!
105+
def evalMacro(mcro: String): String =
106+
Process(Seq("rpm", "--eval", '%' + mcro)).!!
107107
}

src/main/scala/com/typesafe/sbt/packager/rpm/RpmMetadata.scala

+28-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ case class RpmMetadata(
2525
case class RpmDescription(
2626
license: Option[String] = None,
2727
distribution: Option[String] = None,
28-
//vendor: Option[String] = None,
2928
url: Option[String] = None,
3029
group: Option[String] = None,
3130
packager: Option[String] = None,
@@ -75,6 +74,34 @@ case class RpmSpec(meta: RpmMetadata,
7574
mappings: Seq[LinuxPackageMapping] = Seq.empty,
7675
symlinks: Seq[LinuxSymlink] = Seq.empty) {
7776

77+
78+
// TODO - here we want to validate that all the data we have is ok to place
79+
// in the RPM. e.g. the Description/vendor etc. must meet specific requirements.
80+
// For now we just check existence.
81+
def validate(log: Logger): Unit = {
82+
def ensureOr[T](value: T, msg: String, validator: T => Boolean): Boolean = {
83+
if(validator(value)) true
84+
else {
85+
log.error(msg)
86+
false
87+
}
88+
}
89+
def isNonEmpty(s: String): Boolean = !s.isEmpty
90+
val emptyValidators =
91+
Seq(
92+
ensureOr(meta.name, "`name in Rpm` is empty. Please provide one.", isNonEmpty),
93+
ensureOr(meta.version, "`version in Rpm` is empty. Please provide a vaid version for the rpm SPEC.", isNonEmpty),
94+
ensureOr(meta.release, "`rpmRelease in Rpm` is empty. Please provide a valid release number for the rpm SPEC.", isNonEmpty),
95+
ensureOr(meta.arch, "`packageArchitecture in Rpm` is empty. Please provide a valid archiecture for the rpm SPEC.", isNonEmpty),
96+
ensureOr(meta.vendor, "`rpmVendor in Rpm` is empty. Please provide a valid vendor for the rpm SPEC.", isNonEmpty),
97+
ensureOr(meta.os, "`rpmOs in Rpm` is empty. Please provide a valid os vaue for the rpm SPEC.", isNonEmpty),
98+
ensureOr(meta.summary, "`packageSummary in Rpm` is empty. Please provide a valid summary for the rpm SPEC.", isNonEmpty),
99+
ensureOr(meta.description, "`packageDescription in Rpm` is empty. Please provide a valid description for the rpm SPEC.", isNonEmpty)
100+
)
101+
// TODO - Continue validating after this point?
102+
if(!emptyValidators.forall(identity)) sys.error("There are issues with the rpm spec data.")
103+
}
104+
78105
private[this] def fixFilename(n: String): String = {
79106
val tmp =
80107
if(n startsWith "/") n

src/main/scala/com/typesafe/sbt/packager/rpm/RpmPlugin.scala

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ trait RpmPlugin extends Plugin with LinuxPlugin {
5050
rpmSpecConfig <<=
5151
(rpmMetadata, rpmDescription, rpmDependencies, rpmScripts, linuxPackageMappings, linuxPackageSymlinks) map RpmSpec,
5252
packageBin <<= (rpmSpecConfig, target, streams) map { (spec, dir, s) =>
53+
spec.validate(s.log)
5354
RpmHelper.buildRpm(spec, dir, s.log)
5455
},
5556
rpmLint <<= (packageBin, streams) map { (rpm, s) =>

src/main/scala/com/typesafe/sbt/packager/universal/ZipHelper.scala

+3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ object ZipHelper {
4040
}
4141

4242
/** Creates a zip file attempting to give files the appropriate unix permissions using Java 6 APIs.
43+
* Note: This is known to have some odd issues on MacOSX whereby executable permissions
44+
* are not actually discovered, even though the Info-Zip headers exist and work on
45+
* many variants of linux. Yay Apple.
4346
* @param sources The files to include in the zip file.
4447
* @param outputZip The location of the output file.
4548
*/

src/main/scala/com/typesafe/sbt/packager/windows/WixHelper.scala

+5
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,11 @@ object WixHelper {
127127
</Component>
128128
</DirectoryRef>
129129
ComponentInfo(id, xml)
130+
// TODO - To have shortcuts, you MUST put something in the registry. Here,
131+
// We should have shortcuts actually provide us with what they want in the registry,
132+
// rather than forcing it to be something.
133+
// Also, we need some mechanism to ensure the start menu folder is removed in the event
134+
// that we remove all menu items.
130135
case AddShortCuts(targets, workingDir) =>
131136
val id = cleanStringForId("shortcut_" + makeGUID).takeRight(67) // Room for "_SC"
132137
val xml =

0 commit comments

Comments
 (0)