Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

127 lines (122 sloc) 4.844 kb
/* sbt -- Simple Build Tool
* Copyright 2009, 2010 Mark Harrah
*/
package xsbt.boot
import Pre._
import java.io.{File, FileInputStream, InputStreamReader}
import java.net.{MalformedURLException, URI, URL}
import java.util.regex.Pattern
import scala.collection.immutable.List
import annotation.tailrec
object Configuration
{
final val SysPropPrefix = "-D"
def parse(file: URL, baseDirectory: File) = Using( new InputStreamReader(file.openStream, "utf8") )( (new ConfigurationParser).apply )
@tailrec def find(args: List[String], baseDirectory: File): (URL, List[String]) =
args match
{
case head :: tail if head.startsWith("@") => (directConfiguration(head.substring(1), baseDirectory), tail)
case head :: tail if head.startsWith(SysPropPrefix) =>
setProperty(head stripPrefix SysPropPrefix)
find(tail, baseDirectory)
case _ =>
val propertyConfigured = System.getProperty("sbt.boot.properties")
val url = if(propertyConfigured == null) configurationOnClasspath else configurationFromFile(propertyConfigured, baseDirectory)
(url , args)
}
def setProperty(head: String)
{
val keyValue = head.split("=",2)
if(keyValue.length != 2)
System.err.println("Warning: invalid system property '" + head + "'")
else
System.setProperty(keyValue(0), keyValue(1))
}
def configurationOnClasspath: URL =
{
val paths = resourcePaths(guessSbtVersion)
paths.iterator.map(getClass.getResource).find(neNull) getOrElse
( multiPartError("Could not finder sbt launch configuration. Searched classpath for:", paths))
}
def directConfiguration(path: String, baseDirectory: File): URL =
{
try { new URL(path) }
catch { case _: MalformedURLException => configurationFromFile(path, baseDirectory) }
}
def configurationFromFile(path: String, baseDirectory: File): URL =
{
def resolve(against: URI): Option[URL] =
{
val resolved = against.resolve(path)
val exists = try { (new File(resolved)).exists } catch { case _: IllegalArgumentException => false }
if(exists) Some(resolved.toURL) else None
}
val against = resolveAgainst(baseDirectory)
// use Iterators so that resolution occurs lazily, for performance
val resolving = against.iterator.flatMap(e => resolve(e).toList.iterator)
if(!resolving.hasNext) multiPartError("Could not find configuration file '" + path + "'. Searched:", against)
resolving.next()
}
def multiPartError[T](firstLine: String, lines: List[T]) = error( (firstLine :: lines).mkString("\n\t") )
def UnspecifiedVersionPart = "Unspecified"
def DefaultVersionPart = "Default"
def DefaultBuildProperties = "project/build.properties"
def SbtVersionProperty = "sbt.version"
val ConfigurationName = "sbt.boot.properties"
val JarBasePath = "/sbt/"
def userConfigurationPath = "/" + ConfigurationName
def defaultConfigurationPath = JarBasePath + ConfigurationName
val baseResourcePaths: List[String] = userConfigurationPath :: defaultConfigurationPath :: Nil
def resourcePaths(sbtVersion: Option[String]): List[String] =
versionParts(sbtVersion) flatMap { part =>
baseResourcePaths map { base =>
base + part
}
}
def fallbackParts: List[String] = "" :: Nil
def versionParts(version: Option[String]): List[String] =
version match {
case None => UnspecifiedVersionPart :: fallbackParts
case Some(v) => versionParts(v)
}
def versionParts(version: String): List[String] =
{
val pattern = Pattern.compile("""(\d+)\.(\d+)\.(\d+)(-.*)?""")
val m = pattern.matcher(version)
if(m.matches())
subPartsIndices map {_.map(m.group).filter(neNull).mkString(".") }
else
DefaultVersionPart :: fallbackParts
}
private[this] def subPartsIndices =
(1 :: 2 :: Nil) ::
(1 :: 2 :: 3 :: Nil) ::
(1 :: 2 :: 3 :: 4 :: Nil) ::
(Nil) ::
Nil
// the location of project/build.properties and the name of the property within that file
// that configures the sbt version is configured in sbt.boot.properties.
// We have to hard code them here in order to use them to determine the location of sbt.boot.properties itself
def guessSbtVersion: Option[String] =
{
val props = ResolveValues.readProperties(new File(DefaultBuildProperties))
Option(props.getProperty(SbtVersionProperty))
}
def resolveAgainst(baseDirectory: File): List[URI] = (baseDirectory toURI) :: (new File(System.getProperty("user.home")) toURI) ::
toDirectory(classLocation(getClass).toURI) :: Nil
def classLocation(cl: Class[_]): URL =
{
val codeSource = cl.getProtectionDomain.getCodeSource
if(codeSource == null) error("No class location for " + cl)
else codeSource.getLocation
}
def toDirectory(uri: URI): URI =
try
{
val file = new File(uri)
val newFile = if(file.isFile) file.getParentFile else file
newFile.toURI
}
catch { case _: Exception => uri }
private[this] def neNull: AnyRef => Boolean = _ ne null
}
Jump to Line
Something went wrong with that request. Please try again.