mirror of https://github.com/sbt/sbt.git
Extract local, remote, and git BuildLoader.Resolver from ResolveUnit
This commit is contained in:
parent
dd51dbb999
commit
942427bfa3
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
Loading…
Reference in New Issue