sbt/sbt_pending/install/extract/src/main/scala/Main.scala

106 lines
3.7 KiB
Scala

/* sbt -- Simple Build Tool
* Copyright 2009 Mark Harrah
*/
package sbt.extract
import java.io.{File, InputStream}
import java.util.zip.{ZipEntry, ZipFile}
object Main
{
lazy val log: Logger = new ConsoleLogger
def main(args: Array[String])
{
if( args contains "debug" )
log.setLevel(Level.Debug)
val result = OpenResource.zipFile.ioOption(FileUtilities.classLocationFile[Install], "processing", log)(process)
for(msg <- result)
{
log.error(msg)
System.exit(1)
}
}
private[this] val packedGzip = ".pack.gz"
private def isArchive(name: String) = name.endsWith(".gz") || name.endsWith(".zip")
private def process(zip: ZipFile) =
{
val installEntry = zip.getEntry("install")
if(installEntry == null)
Some("Install commands not found.")
else
{
val jarAndZip = wrap.Wrappers.toList(zip.entries).filter(entry => isArchive(entry.getName)).partition(_.getName.endsWith(packedGzip))
jarAndZip match
{
case (Nil, _)=> Some("sbt loader not found.")
case (_, Nil) => Some("Project to extract and build not found.")
case (loaderEntry :: _, projectEntry :: _) => extractAndRun(zip, loaderEntry, projectEntry, installEntry)
}
}
}
private def extractAndRun(zip: ZipFile, loaderEntry: ZipEntry, projectEntry: ZipEntry, installEntry: ZipEntry) =
{
val zipResource = OpenResource.zipEntry(zip)
import FileUtilities.{gunzip, readString, transfer, unzip, writeStream}
val directory = new File(".", trimExtension(projectEntry.getName, ".zip"))
assume(!directory.exists, "Could not extract project: directory " + projectEntry.getName + " exists.")
val loaderBaseName = trimExtension(loaderEntry.getName, packedGzip)
val loaderFile = new File(directory, loaderBaseName + ".jar")
val tempLoaderFile = new File(directory, loaderBaseName + ".pack")
def extractLoader() =
{
implicit def fileToPath(f: File) = Path.fromFile(f)
val result =
writeStream(tempLoaderFile, log) { out => zipResource.ioOption(loaderEntry, "reading", log)(gunzip(_, out, log)) } orElse
Pack.unpack(tempLoaderFile, loaderFile, log)
FileUtilities.clean(tempLoaderFile :: Nil, true, log)
result.toLeft(loaderFile)
}
Control.thread(zipResource.io(installEntry, "reading", log)(readString(_, log))) { installString =>
Control.thread(parseInstall(installString)) { install =>
zipResource.io(projectEntry, "reading", log)(unzip(_, Path.fromFile(directory), log)).left.toOption orElse
Control.thread(extractLoader()) { loaderFile =>
run(loaderFile, directory, install)
}
}
}
}
private def parseInstall(installString: String): Either[String, Install] =
{
installString.split(separator) match
{
case Array(allOptions, allActions) =>
val options = allOptions.split("""\n""").toList
val actions = allActions.split("""\n""").toList
Right( Install(options, actions) )
case _ => Left("Invalid install script (no separator found)")
}
}
private def filterEmpty(list: List[String]) = list.filter(!_.isEmpty)
private def run(loader: File, project: File, install: Install) =
{
val command = "java" :: "-jar" :: loader.getAbsolutePath :: filterEmpty(install.options) ::: filterEmpty(install.actions)
val builder = new java.lang.ProcessBuilder(command.toArray : _*)
builder.directory(project)
val exitCode = (Process(builder) !<)
if(exitCode == 0)
None
else
Some("sbt exited with nonzero exit code: " + exitCode)
}
private def trimExtension(name: String, ext: String) =
{
if(name.endsWith(ext))
name.substring(0, name.length - ext.length)
else
name
}
// keep this in sync with sbt.extract.SelfExtractingProject
private def separator = "===================="
}
private final case class Install(options: List[String], actions: List[String]) extends NotNull