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

Debian scripts are now picked up from default folder #35 #57

Merged
merged 4 commits into from
Oct 31, 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
374 changes: 195 additions & 179 deletions src/main/scala/com/typesafe/sbt/packager/debian/DebianPlugin.scala
Original file line number Diff line number Diff line change
@@ -1,179 +1,195 @@
package com.typesafe.sbt
package packager
package debian

import Keys._
import sbt._
import sbt.Keys.{ mappings, target, name, mainClass, normalizedName }
import linux.LinuxPackageMapping
import linux.LinuxSymlink
import linux.LinuxFileMetaData
import com.typesafe.sbt.packager.Hashing
import com.typesafe.sbt.packager.linux.LinuxSymlink

trait DebianPlugin extends Plugin with linux.LinuxPlugin {
val Debian = config("debian") extend Linux

import com.typesafe.sbt.packager.universal.Archives

private[this] final def copyAndFixPerms(from: File, to: File, perms: LinuxFileMetaData, zipped: Boolean = false): Unit = {
if (zipped) {
IO.withTemporaryDirectory { dir =>
val tmp = dir / from.getName
IO.copyFile(from, tmp)
val zipped = Archives.gzip(tmp)
IO.copyFile(zipped, to, true)
}
} else IO.copyFile(from, to, true)
// If we have a directory, we need to alter the perms.
chmod(to, perms.permissions)
// TODO - Can we do anything about user/group ownership?
}

def debianSettings: Seq[Setting[_]] = Seq(
debianPriority := "optional",
debianSection := "java",
debianPackageDependencies := Seq.empty,
debianPackageRecommends := Seq.empty,
debianSignRole := "builder",
target in Debian <<= (target, name in Debian, version in Debian) apply ((t, n, v) => t / (n + "-" + v)),
name in Debian <<= (name in Linux),
version in Debian <<= (version in Linux),
linuxPackageMappings in Debian <<= linuxPackageMappings,
packageDescription in Debian <<= packageDescription in Linux,
packageSummary in Debian <<= packageSummary in Linux,
maintainer in Debian <<= maintainer in Linux,
debianMaintainerScripts := Seq.empty,
debianMakePreinstScript := None,
debianMakePrermScript := None,
debianMakePostinstScript := None,
debianMakePostrmScript := None,
// TODO - We should make sure there isn't one already specified...
debianMaintainerScripts <++= debianMakePreinstScript map {
case Some(script) => Seq(script -> "preinst")
case None => Seq.empty
},
debianMaintainerScripts <++= debianMakePrermScript map {
case Some(script) => Seq(script -> "prerm")
case None => Seq.empty
},
debianMaintainerScripts <++= debianMakePostinstScript map {
case Some(script) => Seq(script -> "postinst")
case None => Seq.empty
},
debianMaintainerScripts <++= debianMakePostrmScript map {
case Some(script) => Seq(script -> "postrm")
case None => Seq.empty
}) ++ inConfig(Debian)(Seq(
packageArchitecture := "all",
debianPackageInfo <<=
(name, version, maintainer, packageSummary, packageDescription) apply PackageInfo,
debianPackageMetadata <<=
(debianPackageInfo,
debianPriority, packageArchitecture, debianSection,
debianPackageDependencies, debianPackageRecommends) apply PackageMetaData,
debianPackageInstallSize <<= linuxPackageMappings map { mappings =>
(for {
LinuxPackageMapping(files, _, zipped) <- mappings
(file, _) <- files
if !file.isDirectory && file.exists
// TODO - If zipped, heuristically figure out a reduction factor.
} yield file.length).sum / 1024
},
debianControlFile <<= (debianPackageMetadata, debianPackageInstallSize, target) map {
(data, size, dir) =>
val cfile = dir / "DEBIAN" / "control"
IO.write(cfile, data.makeContent(size), java.nio.charset.Charset.defaultCharset)
chmod(cfile, "0644")
cfile
},
debianConffilesFile <<= (linuxPackageMappings, target) map {
(mappings, dir) =>
val cfile = dir / "DEBIAN" / "conffiles"
val conffiles = for {
LinuxPackageMapping(files, meta, _) <- mappings
if meta.config != "false"
(file, name) <- files
if file.isFile
} yield name
IO.writeLines(cfile, conffiles)
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, linuxPackageSymlinks, target) map { (mappings, _, maintScripts, _, symlinks, t) =>
// First Create directories, in case we have any without files in them.
for {
LinuxPackageMapping(files, perms, zipped) <- mappings
(file, name) <- files
if file.isDirectory
tfile = t / name
if !tfile.exists
} tfile.mkdirs()
for {
LinuxPackageMapping(files, perms, zipped) <- mappings
(file, name) <- files
if !file.isDirectory && file.exists
tfile = t / name
} copyAndFixPerms(file, tfile, perms, zipped)

// Now generate relative symlinks
LinuxSymlink.makeSymLinks(symlinks, t, false)

// TODO: Fix this ugly hack to permission directories correctly!
for {
file <- (t.***).get
if file.isDirectory
if file.getCanonicalPath == file.getAbsolutePath // Ignore symlinks.
} chmod(file, "0755")
// Put the maintainer files in `dir / "DEBIAN"` named as specified.
// Valid values for the name are preinst,postinst,prerm,postrm
for ((file, name) <- maintScripts) copyAndFixPerms(file, t / "DEBIAN" / name, LinuxFileMetaData())

t
},
debianMD5sumsFile <<= (debianExplodedPackage, target) map {
(mappings, dir) =>
val md5file = dir / "DEBIAN" / "md5sums"
val md5sums = for {
(file, name) <- (dir.*** --- dir x relativeTo(dir))
if file.isFile
if !(name startsWith "DEBIAN")
if !(name contains "debian-binary")
// TODO - detect symlinks...
if file.getCanonicalPath == file.getAbsolutePath
fixedName = if (name startsWith "/") name drop 1 else name
} yield Hashing.md5Sum(file) + " " + fixedName
IO.writeLines(md5file, md5sums)
chmod(md5file, "0644")
md5file
},
packageBin <<= (debianExplodedPackage, debianMD5sumsFile, target, streams) map { (pkgdir, _, tdir, s) =>
// Make the package. We put this in fakeroot, so we can build the package with root owning files.
Process(Seq("fakeroot", "--", "dpkg-deb", "--build", pkgdir.getAbsolutePath), Some(tdir)) ! s.log match {
case 0 => ()
case x => sys.error("Failure packaging debian file. Exit code: " + x)
}
file(tdir.getAbsolutePath + ".deb")
},
debianSign <<= (packageBin, debianSignRole, streams) map { (deb, role, s) =>
Process(Seq("dpkg-sig", "-s", role, deb.getAbsolutePath), Some(deb.getParentFile())) ! s.log match {
case 0 => ()
case x => sys.error("Failed to sign debian package! exit code: " + x)
}
deb
},
lintian <<= packageBin map { file =>
Process(Seq("lintian", "-c", "-v", file.getName), Some(file.getParentFile)).!
}))

}
package com.typesafe.sbt
package packager
package debian

import Keys._
import sbt._
import sbt.Keys.{ mappings, target, name, mainClass, normalizedName }
import linux.LinuxPackageMapping
import linux.LinuxSymlink
import linux.LinuxFileMetaData
import com.typesafe.sbt.packager.Hashing
import com.typesafe.sbt.packager.linux.LinuxSymlink
import com.typesafe.sbt.packager.archetypes.TemplateWriter

trait DebianPlugin extends Plugin with linux.LinuxPlugin {
val Debian = config("debian") extend Linux

import com.typesafe.sbt.packager.universal.Archives

private[this] final def copyAndFixPerms(from: File, to: File, perms: LinuxFileMetaData, zipped: Boolean = false): Unit = {
if (zipped) {
IO.withTemporaryDirectory { dir =>
val tmp = dir / from.getName
IO.copyFile(from, tmp)
val zipped = Archives.gzip(tmp)
IO.copyFile(zipped, to, true)
}
} else IO.copyFile(from, to, true)
// If we have a directory, we need to alter the perms.
chmod(to, perms.permissions)
// TODO - Can we do anything about user/group ownership?
}

private[this] def filterAndFixPerms(script: File, replacements: DebianControlScriptReplacements, perms: LinuxFileMetaData): File = {
val filtered = TemplateWriter.generateScript(script.toURI.toURL, replacements.makeReplacements)
IO.delete(script)
IO.write(script, filtered)
chmod(script, perms.permissions)
script
}

private[this] def scriptMapping(scriptName: String)(script: Option[File], controlDir: File): Seq[(File, String)] = {
(script, controlDir) match {
case (Some(script), _) => Seq(script -> scriptName)
case (None, dir) =>
val script = dir / scriptName
if (script exists) Seq(file(script getAbsolutePath) -> scriptName) else Seq.empty
}
}

def debianSettings: Seq[Setting[_]] = Seq(
debianPriority := "optional",
debianSection := "java",
debianPackageDependencies := Seq.empty,
debianPackageRecommends := Seq.empty,
debianSignRole := "builder",
target in Debian <<= (target, name in Debian, version in Debian) apply ((t, n, v) => t / (n + "-" + v)),
name in Debian <<= (name in Linux),
version in Debian <<= (version in Linux),
linuxPackageMappings in Debian <<= linuxPackageMappings,
packageDescription in Debian <<= packageDescription in Linux,
packageSummary in Debian <<= packageSummary in Linux,
maintainer in Debian <<= maintainer in Linux,

// Debian Control Scripts
debianControlScriptsReplacements <<= (maintainer in Debian, packageSummary in Debian, normalizedName, version) apply DebianControlScriptReplacements,

debianControlScriptsDirectory := (sourceDirectory.value / "debian" / "DEBIAN"),
debianMaintainerScripts := Seq.empty,
debianMakePreinstScript := None,
debianMakePrermScript := None,
debianMakePostinstScript := None,
debianMakePostrmScript := None,

debianMaintainerScripts <++= (debianMakePrermScript, debianControlScriptsDirectory) map scriptMapping("prerm"),
debianMaintainerScripts <++= (debianMakePreinstScript, debianControlScriptsDirectory) map scriptMapping("preinst"),
debianMaintainerScripts <++= (debianMakePostinstScript, debianControlScriptsDirectory) map scriptMapping("postinst"),
debianMaintainerScripts <++= (debianMakePostrmScript, debianControlScriptsDirectory) map scriptMapping("postrm")) ++ inConfig(Debian)(Seq(
packageArchitecture := "all",
debianPackageInfo <<=
(name, version, maintainer, packageSummary, packageDescription) apply PackageInfo,
debianPackageMetadata <<=
(debianPackageInfo,
debianPriority, packageArchitecture, debianSection,
debianPackageDependencies, debianPackageRecommends) apply PackageMetaData,
debianPackageInstallSize <<= linuxPackageMappings map { mappings =>
(for {
LinuxPackageMapping(files, _, zipped) <- mappings
(file, _) <- files
if !file.isDirectory && file.exists
// TODO - If zipped, heuristically figure out a reduction factor.
} yield file.length).sum / 1024
},
debianControlFile <<= (debianPackageMetadata, debianPackageInstallSize, target) map {
(data, size, dir) =>
val cfile = dir / "DEBIAN" / "control"
IO.write(cfile, data.makeContent(size), java.nio.charset.Charset.defaultCharset)
chmod(cfile, "0644")
cfile
},
debianConffilesFile <<= (linuxPackageMappings, target) map {
(mappings, dir) =>
val cfile = dir / "DEBIAN" / "conffiles"
val conffiles = for {
LinuxPackageMapping(files, meta, _) <- mappings
if meta.config != "false"
(file, name) <- files
if file.isFile
} yield name
IO.writeLines(cfile, conffiles)
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) =>
// First Create directories, in case we have any without files in them.
for {
LinuxPackageMapping(files, perms, zipped) <- mappings
(file, name) <- files
if file.isDirectory
tfile = t / name
if !tfile.exists
} tfile.mkdirs()
for {
LinuxPackageMapping(files, perms, zipped) <- mappings
(file, name) <- files
if !file.isDirectory && file.exists
tfile = t / name
} copyAndFixPerms(file, tfile, perms, zipped)

// Now generate relative symlinks
LinuxSymlink.makeSymLinks(symlinks, t, false)

// TODO: Fix this ugly hack to permission directories correctly!
for {
file <- (t.***).get
if file.isDirectory
if file.getCanonicalPath == file.getAbsolutePath // Ignore symlinks.
} chmod(file, "0755")
// Put the maintainer files in `dir / "DEBIAN"` named as specified.
// Valid values for the name are preinst,postinst,prerm,postrm
for ((file, name) <- maintScripts) {
val targetFile = t / "DEBIAN" / name
copyAndFixPerms(file, targetFile, LinuxFileMetaData())
filterAndFixPerms(targetFile, replacements, LinuxFileMetaData())
}

t
},
debianMD5sumsFile <<= (debianExplodedPackage, target) map {
(mappings, dir) =>
val md5file = dir / "DEBIAN" / "md5sums"
val md5sums = for {
(file, name) <- (dir.*** --- dir x relativeTo(dir))
if file.isFile
if !(name startsWith "DEBIAN")
if !(name contains "debian-binary")
// TODO - detect symlinks...
if file.getCanonicalPath == file.getAbsolutePath
fixedName = if (name startsWith "/") name drop 1 else name
} yield Hashing.md5Sum(file) + " " + fixedName
IO.writeLines(md5file, md5sums)
chmod(md5file, "0644")
md5file
},
packageBin <<= (debianExplodedPackage, debianMD5sumsFile, target, streams) map { (pkgdir, _, tdir, s) =>
// Make the package. We put this in fakeroot, so we can build the package with root owning files.
Process(Seq("fakeroot", "--", "dpkg-deb", "--build", pkgdir.getAbsolutePath), Some(tdir)) ! s.log match {
case 0 => ()
case x => sys.error("Failure packaging debian file. Exit code: " + x)
}
file(tdir.getAbsolutePath + ".deb")
},
debianSign <<= (packageBin, debianSignRole, streams) map { (deb, role, s) =>
Process(Seq("dpkg-sig", "-s", role, deb.getAbsolutePath), Some(deb.getParentFile())) ! s.log match {
case 0 => ()
case x => sys.error("Failed to sign debian package! exit code: " + x)
}
deb
},
lintian <<= packageBin map { file =>
Process(Seq("lintian", "-c", "-v", file.getName), Some(file.getParentFile)).!
}))

}
Loading