Skip to content

Commit

Permalink
Merge pull request #284 from sbt/wip/jdeb
Browse files Browse the repository at this point in the history
First refactoring to provide multiple debian packaging strategies
  • Loading branch information
muuki88 committed Jul 7, 2014
2 parents badecf0 + 137a392 commit 830cac4
Show file tree
Hide file tree
Showing 8 changed files with 425 additions and 227 deletions.
5 changes: 4 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ organization := "com.typesafe.sbt"

scalacOptions in Compile += "-deprecation"

libraryDependencies += "org.apache.commons" % "commons-compress" % "1.4.1"
libraryDependencies ++= Seq(
"org.apache.commons" % "commons-compress" % "1.4.1",
"org.vafer" % "jdeb" % "1.2" artifacts (Artifact("jdeb", "jar", "jar"))
)

site.settings

Expand Down
416 changes: 190 additions & 226 deletions src/main/scala/com/typesafe/sbt/packager/debian/DebianPlugin.scala

Large diffs are not rendered by default.

104 changes: 104 additions & 0 deletions src/main/scala/com/typesafe/sbt/packager/debian/JDebPackaging.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package com.typesafe.sbt
package packager
package debian

import Keys._
import sbt._
import sbt.Keys.{ target, name, normalizedName, TaskStreams }
import linux.{ LinuxFileMetaData, LinuxPackageMapping, LinuxSymlink }
import linux.Keys.{ linuxScriptReplacements, daemonShell }
import com.typesafe.sbt.packager.linux.LinuxPackageMapping
import scala.collection.JavaConversions._

import org.vafer.jdeb.{ DebMaker, DataProducer }
import org.vafer.jdeb.mapping._
import org.vafer.jdeb.producers._
import DebianPlugin.Names

/**
* This provides a java based debian packaging implementation based
* on the jdeb maven-plugin. To use this, put this into your build.sbt
*
* {{
* packageBin in Debian <<= debianJDebPackaging in Debian
* }}
*
* @author Nepomuk Seiler
* @see https://github.com/tcurdt/jdeb/blob/master/src/main/java/org/vafer/jdeb/maven/DebMojo.java#L503
*
*/
trait JDebPackaging { this: DebianPlugin with linux.LinuxPlugin =>

private[debian] def debianJDebSettings: Seq[Setting[_]] = Seq(

/**
* Depends on the 'debianExplodedPackage' task as this creates all the files
* which are defined in the mappings.
*/
debianJDebPackaging <<= (debianExplodedPackage, linuxPackageMappings, linuxPackageSymlinks,
debianControlFile, debianMaintainerScripts, debianConffilesFile,
normalizedName, version, target, streams) map {
(_, mappings, symlinks, controlfile, controlscripts, conffile,
name, version, target, s) =>
s.log.info("Building debian package with java based implementation 'jdeb'")
val console = new JDebConsole(s.log)

val debianFile = target.getParentFile / "%s_%s_all.deb".format(name, version)
val debMaker = new DebMaker(console,
fileAndDirectoryProducers(mappings, target) ++ linkProducers(symlinks),
conffileProducers()
)
debMaker setDeb debianFile
debMaker setControl (target / Names.Debian)

// TODO set compression, gzip is default
// TODO add signing with setKeyring, setKey, setPassphrase, setSignPackage, setSignMethod, setSignRole
debMaker validate ()
debMaker makeDeb ()
debianFile
})

/**
* Creating file and directory producers. These "produce" the
* files for the debian packaging
*/
private[debian] def fileAndDirectoryProducers(mappings: Seq[LinuxPackageMapping], target: File): Seq[DataProducer] = mappings.map {
case LinuxPackageMapping(paths, perms, zipped) =>
// TODO implement mappers here or use the maintainerscripts logic?
val (dirs, files) = paths.partition(_._1.isDirectory)
paths map {
case (path, name) if path.isDirectory =>
new DataProducerDirectory(target / name, null, Array("**"), null)
case (path, name) =>
new DataProducerFile(target / name, name, null, null, null)
}
}.flatten

/**
* Creating link producers for symlinks.
*/
private[debian] def linkProducers(symlinks: Seq[LinuxSymlink]): Seq[DataProducer] = symlinks map {
case LinuxSymlink(link, destination) =>
new DataProducerLink(link, destination, true, null, null, null)
}

/**
* Creating the files which should be added as conffiles.
* This is currently handled by the debian plugin itself.
*/
private[debian] def conffileProducers(): Seq[DataProducer] = Seq.empty

}

/**
* This provides the task for building a debian packaging with
* the java-based implementation jdeb
*/
class JDebConsole(log: Logger) extends org.vafer.jdeb.Console {

def debug(message: String) = log debug message

def info(message: String) = log info message

def warn(message: String) = log warn message
}
3 changes: 3 additions & 0 deletions src/main/scala/com/typesafe/sbt/packager/debian/Keys.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ trait DebianKeys {
val debianPackageMetadata = SettingKey[PackageMetaData]("debian-package-metadata", "Meta data used when constructing a debian package.")
val debianChangelog = SettingKey[Option[File]]("debian-changelog", "The changelog for this deb file")
// Package building
val debianNativePackaging = TaskKey[File]("debian-packaging-native", "Builds the debian package with native cli tools")
val debianJDebPackaging = TaskKey[File]("debian-packaging-jdeb", "Builds the debian package with jdeb (java-based)")

val debianControlFile = TaskKey[File]("debian-control-file", "Makes the debian package control file.")
val debianMaintainerScripts = TaskKey[Seq[(File, String)]]("debian-maintainer-scripts", "Makes the debian maintainer scripts.")
val debianConffilesFile = TaskKey[File]("debian-conffiles-file", "Makes the debian package conffiles file.")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.typesafe.sbt
package packager
package debian

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

/**
* This provides a dpgk based implementation for debian packaging.
* Your machine must have dpkg installed to use this.
*
* {{
* packageBin in Debian <<= debianNativePackaging in Debian
* }}
*
*
*
*/
trait NativePackaging { this: DebianPlugin with linux.LinuxPlugin =>

import com.typesafe.sbt.packager.universal.Archives
import DebianPlugin.Names
import linux.LinuxPlugin.Users

private[debian] def debianNativeSettings: Seq[Setting[_]] = Seq(
genChanges <<= (packageBin, target, debianChangelog, name, version, debianPackageMetadata) map {
(pkg, tdir, changelog, name, version, data) =>
changelog match {
case None => sys.error("Cannot generate .changes file without a changelog")
case Some(chlog) => {
// dpkg-genchanges needs a debian "source" directory, different from the DEBIAN "binary" directory
val debSrc = tdir / "../tmp" / Names.DebianSource
debSrc.mkdirs()
copyAndFixPerms(chlog, debSrc / Names.Changelog, LinuxFileMetaData("0644"))
IO.writeLines(debSrc / Names.Files, List(pkg.getName + " " + data.section + " " + data.priority))
// dpkg-genchanges needs a "source" control file, located in a "debian" directory
IO.writeLines(debSrc / Names.Control, List(data.makeSourceControl()))
val changesFileName = name + "_" + version + "_" + data.architecture + ".changes"
val changesFile: File = tdir / ".." / changesFileName
try {
val changes = Process(Seq("dpkg-genchanges", "-b"), Some(tdir / "../tmp")) !!
val allChanges = List(changes)
IO.writeLines(changesFile, allChanges)
} catch {
case e: Exception => sys.error("Failure generating changes file." + e.getStackTraceString)
}
changesFile
}
}

},
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)).!
},

/** Implementation of the actual packaging */
debianNativePackaging <<= (debianExplodedPackage, debianMD5sumsFile, debianSection, debianPriority, name, version, packageArchitecture, target, streams) map {
(pkgdir, _, section, priority, name, version, arch, tdir, s) =>
s.log.info("Building debian package with native implementation")
// Make the package. We put this in fakeroot, so we can build the package with root owning files.
val archive = name + "_" + version + "_" + arch + ".deb"
Process(Seq("fakeroot", "--", "dpkg-deb", "--build", pkgdir.getAbsolutePath, "../" + archive), Some(tdir)) ! s.log match {
case 0 => ()
case x => sys.error("Failure packaging debian file. Exit code: " + x)
}
tdir / ".." / archive
}
)

}

/**
* This provides the task for building a debian packaging with
* native tools
*
*/
object Native {

/* static assets definitions */

private[debian] def postinstGroupaddTemplateSource: java.net.URL = getClass.getResource("postinst-groupadd")
private[debian] def postinstUseraddTemplateSource: java.net.URL = getClass.getResource("postinst-useradd")
private[debian] def postinstChownTemplateSource: java.net.URL = getClass.getResource("postinst-chown")
private[debian] def postrmPurgeTemplateSource: java.net.URL = getClass.getResource("postrm-purge")
private[debian] def headerSource: java.net.URL = getClass.getResource("header")
}
22 changes: 22 additions & 0 deletions src/sbt-test/debian/simple-jdeb/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import NativePackagerKeys._

packagerSettings

mapGenericFilesToLinux

name := "debian-test"

version := "0.1.0"

maintainer := "Josh Suereth <[email protected]>"

packageSummary := "Test debian package"

packageDescription := """A fun package description of our software,
with multiple lines."""

debianPackageDependencies in Debian ++= Seq("java2-runtime", "bash (>= 2.05a-11)")

debianPackageRecommends in Debian += "git"

packageBin in Debian <<= debianJDebPackaging in Debian
1 change: 1 addition & 0 deletions src/sbt-test/debian/simple-jdeb/project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % sys.props("project.version"))
3 changes: 3 additions & 0 deletions src/sbt-test/debian/simple-jdeb/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Run the debian packaging.
> debian:package-bin
$ exists target/debian-test_0.1.0_all.deb

0 comments on commit 830cac4

Please sign in to comment.