mirror of https://github.com/sbt/sbt.git
106 lines
3.7 KiB
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 |