mirror of https://github.com/sbt/sbt.git
79 lines
3.0 KiB
Scala
79 lines
3.0 KiB
Scala
/* sbt -- Simple Build Tool
|
|
* Copyright 2009 Mark Harrah
|
|
*/
|
|
package sbt.extract
|
|
|
|
import java.io.{ByteArrayOutputStream, File}
|
|
import FileUtilities.{classLocationFile, clean, createTemporaryDirectory, download, transferAndClose, unzip, write, zip}
|
|
import SelfExtractingProject.{flat, separator}
|
|
|
|
trait SelfExtractingProject extends Project
|
|
{
|
|
protected def createSelfExtractingJar(actions: List[String], jvmOptions: List[String], projectZip: Path, outputJar: Path): Option[String] =
|
|
{
|
|
def jarForClass(name: String) = Path.fromFile(classLocationFile(Class.forName(name)))
|
|
val loaderJar = jarForClass("xsbti.Launcher")
|
|
val bytes = new ByteArrayOutputStream
|
|
transferAndClose(this.getClass.getResourceAsStream("extract.location"), bytes, log) orElse
|
|
{
|
|
val extractorJarLocation = bytes.toString("UTF-8")
|
|
createSelfExtractingJar(actions, jvmOptions, projectZip, loaderJar, extractorJarLocation, outputJar)
|
|
}
|
|
}
|
|
private def createSelfExtractingJar(actions: List[String], jvmOptions: List[String], projectZip: Path, loaderJar: Path, extractorJarLocation: String, outputJar: Path): Option[String] =
|
|
{
|
|
val installContents = jvmOptions.mkString("\n") + separator + actions.mkString("\n")
|
|
withTemporaryDirectory(log) { tmp =>
|
|
val tmpPath = Path.fromFile(tmp)
|
|
write(new File(tmp, "install"), installContents, log) orElse
|
|
unzip(this.getClass.getResource(extractorJarLocation), tmpPath, log).left.toOption orElse
|
|
Control.thread(compressLoader(loaderJar)) { compressedLoader =>
|
|
zip( (tmpPath ###) :: flat(projectZip) :: compressedLoader :: Nil, outputJar, true, log)
|
|
}
|
|
}
|
|
}
|
|
private def withTemporaryDirectory(log: Logger)(f: File => Option[String]) =
|
|
{
|
|
Control.thread(createTemporaryDirectory(log)) { dir =>
|
|
Control.trapUnitAndFinally("", log)
|
|
{ f(dir) }
|
|
{ clean(Path.fromFile(dir) :: Nil, true, log) }
|
|
}
|
|
}
|
|
private def compressLoader(loaderJar: Path): Either[String, Path] =
|
|
{
|
|
val jarName = loaderJar.asFile.getName
|
|
val dotIndex = jarName.lastIndexOf('.')
|
|
val baseName =
|
|
if(dotIndex > 0) jarName.substring(0, dotIndex)
|
|
else jarName
|
|
val packedName = baseName + ".pack"
|
|
val packed = outputPath / packedName
|
|
val packedAndGzip = (outputPath ###) / (packedName + ".gz")
|
|
val result =
|
|
Pack.pack(loaderJar, packed, log) orElse
|
|
FileUtilities.gzip(packed, packedAndGzip, log)
|
|
result.toLeft(packedAndGzip)
|
|
}
|
|
}
|
|
trait BasicSelfExtractingProject extends BasicScalaProject with SelfExtractingProject
|
|
{
|
|
def installActions: List[String] = update.name :: `package`.name :: Nil
|
|
def jvmOptions: List[String] = Nil
|
|
def selfExtractingJar: Path = outputPath / (artifactBaseName + "-setup.jar")
|
|
|
|
lazy val installer = installerAction
|
|
def installerAction = task { createSelfExtractingJar(installActions, jvmOptions, packageProjectZip, selfExtractingJar) } dependsOn packageProject
|
|
}
|
|
|
|
object SelfExtractingProject
|
|
{
|
|
// keep this in sync with sbt.extract.Main.separator
|
|
def separator = "===================="
|
|
private def flat(p: Path) =
|
|
p match
|
|
{
|
|
case rp: RelativePath => (rp.parentPath ###) / rp.component
|
|
case _ => p
|
|
}
|
|
} |