Extract local, remote, and git BuildLoader.Resolver from ResolveUnit

This commit is contained in:
Sanjin Sehic 2011-12-19 08:43:08 +01:00 committed by Mark Harrah
parent dd51dbb999
commit 942427bfa3
4 changed files with 143 additions and 67 deletions

View File

@ -5,6 +5,7 @@ package sbt
import java.io.File
import java.net.URI
import BuildLoader.ResolveInfo
import compiler.{Eval, EvalImports}
import complete.DefaultParsers.validID
import Compiler.Compilers
@ -38,78 +39,25 @@ object Build
}
object RetrieveUnit
{
def apply(tempDir: File, base: URI): Option[() => File] =
def apply(info: ResolveInfo): Option[() => File] =
{
lazy val tmp = temporary(tempDir, base)
base.getScheme match
{
case "git" => gitApply(tmp, base)
case _ if isGitPath(base.getPath) => gitApply(tmp, base)
case "http" | "https" => Some { () => downloadAndExtract(base, tmp); tmp }
case "file" =>
val f = new File(base)
if(f.isDirectory)
{
val finalDir = if (!f.canWrite) retrieveRODir(f, tmp) else f
Some(() => finalDir)
}
else None
info.uri match {
case Scheme("git") => Resolvers.git(info)
case Path(path) if path.endsWith(".git") => Resolvers.git(info)
case Scheme("http") | Scheme("https") | Scheme("ftp") => Resolvers.remote(info)
case Scheme("file") => Resolvers.local(info)
case _ => None
}
}
def isGitPath(path: String) = path.endsWith(".git")
private[this] def gitApply(tmp: File, base: URI) = Some { () => gitRetrieve(base, tmp); tmp }
def retrieveRODir(base: File, tempDir: File): File =
{
if (!tempDir.exists)
{
try {
IO.copyDirectory(base, tempDir)
} catch {
case e =>
IO.delete(tempDir)
throw e
}
}
tempDir
}
def downloadAndExtract(base: URI, tempDir: File): Unit = if(!tempDir.exists) IO.unzipURL(base.toURL, tempDir)
def temporary(tempDir: File, uri: URI): File = new File(tempDir, Hash.halve(hash(uri)))
def hash(uri: URI): String = Hash.toHex(Hash(uri.toASCIIString))
import Process._
def gitRetrieve(base: URI, tempDir: File): Unit =
if(!tempDir.exists)
{
try {
IO.createDirectory(tempDir)
gitClone(dropFragment(base), tempDir)
Option(base.getFragment) foreach { branch => gitCheckout(tempDir, branch) }
} catch {
case e => IO.delete(tempDir)
throw e
}
}
def dropFragment(base: URI): URI = if(base.getFragment eq null) base else new URI(base.getScheme, base.getSchemeSpecificPart, null)
def gitClone(base: URI, tempDir: File): Unit =
git("clone" :: dropFragment(base).toASCIIString :: tempDir.getAbsolutePath :: Nil, tempDir) ;
def gitCheckout(tempDir: File, branch: String): Unit =
git("checkout" :: "-q" :: branch :: Nil, tempDir)
def git(args: List[String], cwd: File): Unit =
if(isWindowsShell) run(List("cmd", "/c", "git") ++ args, cwd)
else run("git" +: args, cwd)
lazy val isWindowsShell = {
val ostype = System.getenv("OSTYPE")
val isCygwin = ostype != null && ostype.toLowerCase.contains("cygwin")
val isWindows = System.getProperty("os.name", "").toLowerCase.contains("windows")
isWindows && !isCygwin
}
def run(command: List[String], cwd: File): Unit =
object Scheme
{
val result = Process(command, cwd) ! ;
if(result != 0)
error("Nonzero exit code (" + result + "): " + command.mkString(" "))
def unapply(uri: URI) = Option(uri.getScheme)
}
object Path
{
def unapply(uri: URI) = Option(uri.getPath)
}
}
object EvaluateConfigurations

View File

@ -231,7 +231,7 @@ object Load
def load(file: File, s: State, config: LoadBuildConfiguration): PartBuild =
{
val fail = (uri: URI) => error("Invalid build URI (no handler available): " + uri)
val resolver = (info: BuildLoader.ResolveInfo) => RetrieveUnit(info.staging, info.uri)
val resolver = (info: BuildLoader.ResolveInfo) => RetrieveUnit(info)
val build = (info: BuildLoader.BuildInfo) => Some(() => loadUnit(info.uri, info.base, info.state, info.config))
val components = BuildLoader.components(resolver, build, full = BuildLoader.componentLoader)
val builtinLoader = BuildLoader(components, fail, s, config)

105
main/Resolvers.scala Normal file
View File

@ -0,0 +1,105 @@
/* sbt -- Simple Build Tool
* Copyright 2011 Sanjin Sehic
*/
package sbt
import java.io.File
import java.net.URI
import BuildLoader.ResolveInfo
import RichURI.fromURI
object Resolvers
{
type Resolver = BuildLoader.Resolver
val local: Resolver = (info: ResolveInfo) => {
def retrieveRODir(at: File, into: File) = creates(into) {IO.copyDirectory(at, into)}
val uri = info.uri
val dir = new File(uri)
if (dir.isDirectory) {
Some {
() =>
if (dir.canWrite)
dir
else
retrieveRODir(at = dir, into = uniqueSubdirectoryFor(uri, in = info.staging))
}
} else None
}
val remote: Resolver = (info: ResolveInfo) => {
def downloadAndExtract(at: URI, into: File) = creates(into) {IO.unzipURL(at.toURL, into)}
val uri = info.uri
Some {
() =>
downloadAndExtract(at = uri, into = uniqueSubdirectoryFor(uri, in = info.staging))
}
}
val git: Resolver = (info: ResolveInfo) => {
def clone(at: String, into: File)
{
run(None, "git", "clone", at, into.getAbsolutePath)
}
def checkout(branch: String, in: File)
{
run(Some(in), "git", "checkout", "-q", branch)
}
def retrieveLocalCopy(at: URI, into: File) =
{
creates(into) {
clone(at.withoutFragment.toASCIIString, into)
if (at.hasFragment)
checkout(branch = at.getFragment, in = into)
}
}
val uri = info.uri
Some {
() =>
retrieveLocalCopy(at = uri, into = uniqueSubdirectoryFor(uri, in = info.staging))
}
}
private lazy val onWindows = {
val os = System.getenv("OSTYPE")
val isCygwin = (os != null) && os.toLowerCase.contains("cygwin")
val isWindows = System.getProperty("os.name", "").toLowerCase.contains("windows")
isWindows && !isCygwin
}
def run(cwd: Option[File], command: String*)
{
val result =
Process(
if (onWindows)
"cmd" +: "/c" +: command
else
command,
cwd
) !;
if (result != 0)
error("Nonzero exit code (" + result + "): " + command.mkString(" "))
}
def creates(file: File)(f: => Unit) =
{
try {
if (!file.exists)
f
file
} catch {
case e =>
IO.delete(file)
throw e
}
}
def uniqueSubdirectoryFor(uri: URI, in: File) = new File(in, Hash.halfHashString(uri.toASCIIString))
}

23
util/io/RichURI.scala Normal file
View File

@ -0,0 +1,23 @@
/* sbt -- Simple Build Tool
* Copyright 2011 Sanjin Sehic
*/
package sbt
import java.net.URI
class RichURI(uri: URI)
{
def hasFragment = uri.getFragment ne null
def withoutFragment =
if (hasFragment)
new URI(uri.getScheme, uri.getSchemeSpecificPart, null)
else
uri
}
object RichURI
{
implicit def fromURI(uri: URI) = new RichURI(uri)
}