Add dist task for building download zip. Fixes #1001

Simpler than what was there before. Just a single zip file
is being created. Extending this should be coordinated
with Josh's work on the integrated typesafe stack build.

Also add caching to rstdoc task.
This commit is contained in:
Peter Vlugter 2011-12-13 14:40:21 +13:00
parent f4b8e9cfa6
commit 531397edc2
4 changed files with 127 additions and 15 deletions

View file

@ -24,10 +24,11 @@ object AkkaBuild extends Build {
lazy val akka = Project(
id = "akka",
base = file("."),
settings = parentSettings ++ Release.settings ++ Unidoc.settings ++ Rstdoc.settings ++ Publish.versionSettings ++ Seq(
settings = parentSettings ++ Release.settings ++ Unidoc.settings ++ Rstdoc.settings ++ Publish.versionSettings ++ Dist.settings ++ Seq(
parallelExecution in GlobalScope := false,
Publish.defaultPublishTo in ThisBuild <<= crossTarget / "repository",
Unidoc.unidocExclude := Seq(samples.id, tutorials.id)
Unidoc.unidocExclude := Seq(samples.id, tutorials.id),
Dist.distExclude := Seq(actorTests.id, akkaSbtPlugin.id, docs.id)
),
aggregate = Seq(actor, testkit, actorTests, stm, remote, slf4j, amqp, mailboxes, akkaSbtPlugin, samples, tutorials, docs)
)

98
project/Dist.scala Normal file
View file

@ -0,0 +1,98 @@
package akka
import sbt._
import sbt.Keys._
import sbt.classpath.ClasspathUtilities
import sbt.Project.Initialize
import java.io.File
object Dist {
case class DistSources(depJars: Seq[File], libJars: Seq[File], srcJars: Seq[File], docJars: Seq[File], api: File, docs: File)
val distExclude = SettingKey[Seq[String]]("dist-exclude")
val distAllClasspaths = TaskKey[Seq[Classpath]]("dist-all-classpaths")
val distDependencies = TaskKey[Seq[File]]("dist-dependencies")
val distLibJars = TaskKey[Seq[File]]("dist-lib-jars")
val distSrcJars = TaskKey[Seq[File]]("dist-src-jars")
val distDocJars = TaskKey[Seq[File]]("dist-doc-jars")
val distSources = TaskKey[DistSources]("dist-sources")
val distDirectory = SettingKey[File]("dist-directory")
val distUnzipped = SettingKey[File]("dist-unzipped")
val distFile = SettingKey[File]("dist-file")
val dist = TaskKey[File]("dist", "Create a zipped distribution of everything.")
lazy val settings: Seq[Setting[_]] = Seq(
distExclude := Seq.empty,
distAllClasspaths <<= (thisProjectRef, buildStructure, distExclude) flatMap aggregated(dependencyClasspath.task in Compile),
distDependencies <<= distAllClasspaths map { _.flatten.map(_.data).filter(ClasspathUtilities.isArchive).distinct },
distLibJars <<= (thisProjectRef, buildStructure, distExclude) flatMap aggregated(packageBin.task in Compile),
distSrcJars <<= (thisProjectRef, buildStructure, distExclude) flatMap aggregated(packageSrc.task in Compile),
distDocJars <<= (thisProjectRef, buildStructure, distExclude) flatMap aggregated(packageDoc.task in Compile),
distSources <<= (distDependencies, distLibJars, distSrcJars, distDocJars, Unidoc.unidoc, Rstdoc.rstdoc) map DistSources,
distDirectory <<= crossTarget / "dist",
distUnzipped <<= distDirectory / "unzipped",
distFile <<= (distDirectory, version) { (dir, v) => dir / ("akka-" + v + ".zip") },
dist <<= distTask
)
def aggregated[T](task: SettingKey[Task[T]])(projectRef: ProjectRef, structure: Load.BuildStructure, exclude: Seq[String]): Task[Seq[T]] = {
val projects = aggregatedProjects(projectRef, structure, exclude)
projects flatMap { task in LocalProject(_) get structure.data } join
}
def aggregatedProjects(projectRef: ProjectRef, structure: Load.BuildStructure, exclude: Seq[String]): Seq[String] = {
val aggregate = Project.getProject(projectRef, structure).toSeq.flatMap(_.aggregate)
aggregate flatMap { ref =>
if (exclude contains ref.project) Seq.empty
else ref.project +: aggregatedProjects(ref, structure, exclude)
}
}
def distTask: Initialize[Task[File]] = {
(baseDirectory, distSources, distUnzipped, version, distFile, streams) map {
(projectBase, allSources, unzipped, version, zipFile, s) => {
val base = unzipped / ("akka-" + version)
val scripts = (projectBase / "scripts" / "microkernel" * "*").get
val bin = base / "bin"
val configSources = projectBase / "config"
val config = base / "config"
val doc = base / "doc" / "akka"
val api = doc / "api"
val docs = doc / "docs"
val docJars = doc / "jars"
val libs = allSources.depJars ++ allSources.libJars
val (scalaLibs, akkaLibs) = libs partition (_.name.contains("scala-library"))
val lib = base / "lib"
val libAkka = lib / "akka"
val src = base / "src" / "akka"
IO.delete(unzipped)
//createStructure(doc, docJars, lib, src)
copyFilesTo(scripts, bin, setExecutable = true)
IO.copyDirectory(configSources, config)
IO.copyDirectory(allSources.api, api)
IO.copyDirectory(allSources.docs, docs)
copyFilesTo(allSources.docJars, docJars)
copyFilesTo(scalaLibs, lib)
copyFilesTo(akkaLibs, libAkka)
copyFilesTo(allSources.srcJars, src)
val files = unzipped ** -DirectoryFilter
val sources = files x relativeTo(unzipped)
IO.zip(sources, zipFile)
zipFile
}
}
}
def createStructure(dirs: File*): Unit = {
dirs foreach IO.createDirectory
}
def copyFilesTo(files: Seq[File], dir: File, setExecutable: Boolean = false): Unit = {
IO.createDirectory(dir)
for (file <- files) {
val target = dir / file.name
IO.copyFile(file, target)
if (setExecutable) target.setExecutable(file.canExecute, false)
}
}
}

View file

@ -24,11 +24,13 @@ object Release {
val state1 = extracted.runAggregated(publish in projectRef, state)
val (state2, api) = extracted.runTask(Unidoc.unidoc, state1)
val (state3, docs) = extracted.runTask(Rstdoc.rstdoc, state2)
val (state4, dist) = extracted.runTask(Dist.dist, state3)
IO.delete(release)
IO.createDirectory(release)
IO.copyDirectory(repo, release / "releases")
IO.copyDirectory(api, release / "api" / "akka" / releaseVersion)
IO.copyDirectory(docs, release / "docs" / "akka" / releaseVersion)
state3
IO.copyFile(dist, release / "downloads" / dist.name)
state4
}
}

View file

@ -15,19 +15,30 @@ object Rstdoc {
rstdoc <<= rstdocTask
)
def rstdocTask = (rstdocDirectory, rstdocTarget, streams) map {
(dir, target, s) => {
s.log.info("Building reStructuredText documentation...")
val logger = new ProcessLogger {
def info(o: => String): Unit = s.log.debug(o)
def error(e: => String): Unit = s.log.debug(e)
def buffer[T](f: => T): T = f
def rstdocTask = (cacheDirectory, rstdocDirectory, rstdocTarget, streams) map {
(cacheDir, dir, target, s) => {
val cache = cacheDir / "rstdoc"
val cached = FileFunction.cached(cache)(FilesInfo.hash, FilesInfo.exists) { (in, out) =>
val changes = in.modified
if (!changes.isEmpty) {
s.log.info("Building reStructuredText documentation...")
changes.foreach(file => s.log.debug("Changed documentation source: " + file))
val logger = new ProcessLogger {
def info(o: => String): Unit = s.log.debug(o)
def error(e: => String): Unit = s.log.debug(e)
def buffer[T](f: => T): T = f
}
val exitCode = Process(List("make", "clean", "html", "pdf"), dir) ! logger
if (exitCode != 0) sys.error("Failed to build docs.")
s.log.info("Creating reStructuredText documentation successful.")
IO.copyDirectory(dir / "_build" / "html", target)
IO.copyFile(dir / "_build" / "latex" / "Akka.pdf", target / "Akka.pdf")
target.descendentsExcept("*", "").get.toSet
} else Set.empty
}
val exitCode = Process(List("make", "clean", "html", "pdf"), dir) ! logger
if (exitCode != 0) sys.error("Failed to build docs.")
s.log.info("Creating reStructuredText documentation successful.")
IO.copyDirectory(dir / "_build" / "html", target)
IO.copyFile(dir / "_build" / "latex" / "Akka.pdf", target / "Akka.pdf")
val toplevel = dir * ("*" - ".*" - "_sphinx" - "_build" - "disabled" - "target")
val inputs = toplevel.descendentsExcept("*", "").get.toSet
cached(inputs)
target
}
}