Merge 'vjovanov/0.12' into 0.12

This commit is contained in:
Mark Harrah 2012-04-12 17:21:08 -04:00
commit 2aad26a5ba
8 changed files with 70 additions and 43 deletions

View File

@ -53,10 +53,11 @@ private object BootConfiguration
val DefaultIvyConfiguration = "default"
/** The name of the directory within the boot directory to retrieve scala to. */
val ScalaDirectoryName = "lib"
/** The Ivy pattern to use for retrieving the scala compiler and library. It is relative to the directory
* containing all jars for the requested version of scala. */
* containing all jars for the requested version of scala.
*/
val scalaRetrievePattern = ScalaDirectoryName + "/[artifact](-[classifier]).[ext]"
def artifactType(classifier: String) =
@ -71,19 +72,23 @@ private object BootConfiguration
* containing all jars for the requested version of scala. */
def appRetrievePattern(appID: xsbti.ApplicationID) = appDirectoryName(appID, "/") + "(/[component])/[artifact]-[revision](-[classifier]).[ext]"
val ScalaDirPrefix = "scala-"
val ScalaVersionPrefix = "scala-"
/** The name of the directory to retrieve the application and its dependencies to.*/
def appDirectoryName(appID: xsbti.ApplicationID, sep: String) = appID.groupID + sep + appID.name + sep + appID.version
/** The name of the directory in the boot directory to put all jars for the given version of scala in.*/
def baseDirectoryName(scalaVersion: Option[String]) = scalaVersion match {
def baseDirectoryName(scalaOrg: String, scalaVersion: Option[String]) = scalaVersion match {
case None => "other"
case Some(sv) => ScalaDirPrefix + sv
case Some(sv) => (if (scalaOrg == ScalaOrg) "" else scalaOrg + ".") + ScalaVersionPrefix + sv
}
def extractScalaVersion(dir: File): Option[String] =
{
val name = dir.getName
if(name.startsWith(ScalaDirPrefix)) Some(name.substring(ScalaDirPrefix.length)) else None
if(name.contains(ScalaVersionPrefix))
Some(name.substring(name.lastIndexOf(ScalaVersionPrefix) + ScalaVersionPrefix.length))
else
None
}
}
private object ProxyProperties

View File

@ -77,17 +77,18 @@ object Launch
}
final class RunConfiguration(val scalaVersion: Option[String], val app: xsbti.ApplicationID, val workingDirectory: File, val arguments: List[String])
import BootConfiguration.{appDirectoryName, baseDirectoryName, extractScalaVersion, ScalaDirectoryName, TestLoadScalaClasses}
import BootConfiguration.{appDirectoryName, baseDirectoryName, extractScalaVersion, ScalaDirectoryName, TestLoadScalaClasses, ScalaOrg}
class Launch private[xsbt](val bootDirectory: File, val lockBoot: Boolean, val ivyOptions: IvyOptions) extends xsbti.Launcher
{
import ivyOptions.{checksums => checksumsList, classifiers, repositories}
bootDirectory.mkdirs
private val scalaProviders = new Cache[String, String, xsbti.ScalaProvider](getScalaProvider(_,_))
private val scalaProviders = new Cache[(String, String), String, xsbti.ScalaProvider]((x, y) => getScalaProvider(x._1, x._2, y))
def getScala(version: String): xsbti.ScalaProvider = getScala(version, "")
def getScala(version: String, reason: String): xsbti.ScalaProvider = scalaProviders(version, reason)
def getScala(version: String, reason: String): xsbti.ScalaProvider = getScala(version, reason, ScalaOrg)
def getScala(version: String, reason: String, scalaOrg: String) = scalaProviders((scalaOrg, version), reason)
def app(id: xsbti.ApplicationID, version: String): xsbti.AppProvider = app(id, Option(version))
def app(id: xsbti.ApplicationID, scalaVersion: Option[String]): xsbti.AppProvider =
getAppProvider(id, scalaVersion, false)
def app(id: xsbti.ApplicationID, scalaVersion: Option[String]): xsbti.AppProvider =
getAppProvider(id, scalaVersion, false)
val bootLoader = new BootFilteredLoader(getClass.getClassLoader)
val topLoader = jnaLoader(bootLoader)
@ -102,8 +103,8 @@ class Launch private[xsbt](val bootDirectory: File, val lockBoot: Boolean, val i
def jnaLoader(parent: ClassLoader): ClassLoader =
{
val id = AppID("net.java.dev.jna", "jna", "3.2.3", "", toArray(Nil), false, array())
val configuration = makeConfiguration(None)
val jnaHome = appDirectory(new File(bootDirectory, baseDirectoryName(None)), id)
val configuration = makeConfiguration(ScalaOrg, None)
val jnaHome = appDirectory(new File(bootDirectory, baseDirectoryName(ScalaOrg, None)), id)
val module = appModule(id, None, false, "jna")
def makeLoader(): ClassLoader = {
val urls = toURLs(wrapNull(jnaHome.listFiles(JarFilter)))
@ -129,8 +130,8 @@ class Launch private[xsbt](val bootDirectory: File, val lockBoot: Boolean, val i
module.retrieveCorrupt(missing)
}
private[this] def makeConfiguration(version: Option[String]): UpdateConfiguration =
new UpdateConfiguration(bootDirectory, ivyOptions.ivyHome, version, repositories, checksumsList)
private[this] def makeConfiguration(scalaOrg: String, version: Option[String]): UpdateConfiguration =
new UpdateConfiguration(bootDirectory, ivyOptions.ivyHome, scalaOrg, version, repositories, checksumsList)
final def getAppProvider(id: xsbti.ApplicationID, explicitScalaVersion: Option[String], forceAppUpdate: Boolean): xsbti.AppProvider =
locked(new Callable[xsbti.AppProvider] { def call = getAppProvider0(id, explicitScalaVersion, forceAppUpdate) })
@ -142,14 +143,14 @@ class Launch private[xsbt](val bootDirectory: File, val lockBoot: Boolean, val i
def retrieve() = {
val sv = update(app, "")
val scalaVersion = strictOr(explicitScalaVersion, sv)
new RetrievedModule(true, app, sv, baseDirs(scalaHome(scalaVersion)))
new RetrievedModule(true, app, sv, baseDirs(scalaHome(ScalaOrg, scalaVersion)))
}
val retrievedApp =
if(forceAppUpdate)
retrieve()
else
existing(app, explicitScalaVersion, baseDirs) getOrElse retrieve()
existing(app, ScalaOrg, explicitScalaVersion, baseDirs) getOrElse retrieve()
val scalaVersion = getOrError(strictOr(explicitScalaVersion, retrievedApp.detectedScalaVersion), "No Scala version specified or detected")
val scalaProvider = getScala(scalaVersion, "(for " + id.name + ")")
@ -161,8 +162,8 @@ class Launch private[xsbt](val bootDirectory: File, val lockBoot: Boolean, val i
else
getAppProvider0(id, explicitScalaVersion, true)
}
def scalaHome(scalaVersion: Option[String]): File = new File(bootDirectory, baseDirectoryName(scalaVersion))
def appHome(id: xsbti.ApplicationID, scalaVersion: Option[String]): File = appDirectory(scalaHome(scalaVersion), id)
def scalaHome(scalaOrg: String, scalaVersion: Option[String]): File = new File(bootDirectory, baseDirectoryName(scalaOrg, scalaVersion))
def appHome(id: xsbti.ApplicationID, scalaVersion: Option[String]): File = appDirectory(scalaHome(ScalaOrg, scalaVersion), id)
def checkedAppProvider(id: xsbti.ApplicationID, module: RetrievedModule, scalaProvider: xsbti.ScalaProvider): (Iterable[String], xsbti.AppProvider) =
{
val p = appProvider(id, module, scalaProvider, appHome(id, Some(scalaProvider.version)))
@ -170,19 +171,19 @@ class Launch private[xsbt](val bootDirectory: File, val lockBoot: Boolean, val i
(missing, p)
}
private[this] def locked[T](c: Callable[T]): T = Locks(orNull(updateLockFile), c)
def getScalaProvider(scalaVersion: String, reason: String): xsbti.ScalaProvider =
locked(new Callable[xsbti.ScalaProvider] { def call = getScalaProvider0(scalaVersion, reason) })
def getScalaProvider(scalaOrg: String, scalaVersion: String, reason: String): xsbti.ScalaProvider =
locked(new Callable[xsbti.ScalaProvider] { def call = getScalaProvider0(scalaOrg, scalaVersion, reason) })
private[this] final def getScalaProvider0(scalaVersion: String, reason: String) =
private[this] final def getScalaProvider0(scalaOrg: String, scalaVersion: String, reason: String) =
{
val scalaM = scalaModule(scalaVersion)
val (scalaHome, lib) = scalaDirs(scalaM, scalaVersion)
val scalaM = scalaModule(scalaOrg, scalaVersion)
val (scalaHome, lib) = scalaDirs(scalaM, scalaOrg, scalaVersion)
val baseDirs = lib :: Nil
def provider(retrieved: RetrievedModule): xsbti.ScalaProvider = {
val p = scalaProvider(scalaVersion, retrieved, topLoader, lib)
checkLoader(p.loader, retrieved.definition, TestLoadScalaClasses, p)
}
existing(scalaM, Some(scalaVersion), _ => baseDirs) flatMap { mod =>
existing(scalaM, scalaOrg, Some(scalaVersion), _ => baseDirs) flatMap { mod =>
try Some(provider(mod))
catch { case e: Exception => None }
} getOrElse {
@ -191,10 +192,10 @@ class Launch private[xsbt](val bootDirectory: File, val lockBoot: Boolean, val i
}
}
def existing(module: ModuleDefinition, explicitScalaVersion: Option[String], baseDirs: File => List[File]): Option[RetrievedModule] =
def existing(module: ModuleDefinition, scalaOrg: String, explicitScalaVersion: Option[String], baseDirs: File => List[File]): Option[RetrievedModule] =
{
val filter = new java.io.FileFilter {
val explicitName = explicitScalaVersion.map(sv => baseDirectoryName(Some(sv)))
val explicitName = explicitScalaVersion.map(sv => baseDirectoryName(scalaOrg, Some(sv)))
def accept(file: File) = file.isDirectory && explicitName.forall(_ == file.getName)
}
val retrieved = wrapNull(bootDirectory.listFiles(filter)) flatMap { scalaDir =>
@ -219,9 +220,9 @@ class Launch private[xsbt](val bootDirectory: File, val lockBoot: Boolean, val i
def appDirectory(base: File, id: xsbti.ApplicationID): File =
new File(base, appDirectoryName(id, File.separator))
def scalaDirs(module: ModuleDefinition, scalaVersion: String): (File, File) =
def scalaDirs(module: ModuleDefinition, scalaOrg: String, scalaVersion: String): (File, File) =
{
val scalaHome = new File(bootDirectory, baseDirectoryName(Some(scalaVersion)))
val scalaHome = new File(bootDirectory, baseDirectoryName(scalaOrg, Some(scalaVersion)))
val libDirectory = new File(scalaHome, ScalaDirectoryName)
(scalaHome, libDirectory)
}
@ -257,13 +258,13 @@ class Launch private[xsbt](val bootDirectory: File, val lockBoot: Boolean, val i
}
def appModule(id: xsbti.ApplicationID, scalaVersion: Option[String], getClassifiers: Boolean, tpe: String): ModuleDefinition = new ModuleDefinition(
configuration = makeConfiguration(scalaVersion),
configuration = makeConfiguration(ScalaOrg, scalaVersion),
target = new UpdateApp(Application(id), if(getClassifiers) Value.get(classifiers.app) else Nil, tpe),
failLabel = id.name + " " + id.version,
extraClasspath = id.classpathExtra
)
def scalaModule(version: String): ModuleDefinition = new ModuleDefinition(
configuration = makeConfiguration(Some(version)),
def scalaModule(org: String, version: String): ModuleDefinition = new ModuleDefinition(
configuration = makeConfiguration(org, Some(version)),
target = new UpdateScala(Value.get(classifiers.forScala)),
failLabel = "Scala " + version,
extraClasspath = array()

View File

@ -15,12 +15,14 @@ final case class LaunchConfiguration(scalaVersion: Value[String], ivyConfigurati
val sv = Value.get(scalaVersion)
if(sv == "auto") None else Some(sv)
}
def withScalaVersion(newScalaVersion: String) = LaunchConfiguration(new Explicit(newScalaVersion), ivyConfiguration, app, boot, logging, appProperties)
def withApp(app: Application) = LaunchConfiguration(scalaVersion, ivyConfiguration, app, boot, logging, appProperties)
def withAppVersion(newAppVersion: String) = LaunchConfiguration(scalaVersion, ivyConfiguration, app.withVersion(new Explicit(newAppVersion)), boot, logging, appProperties)
// TODO: withExplicit
def withVersions(newScalaVersion: String, newAppVersion: String, classifiers0: Classifiers) =
LaunchConfiguration(new Explicit(newScalaVersion), ivyConfiguration.copy(classifiers = classifiers0), app.withVersion(new Explicit(newAppVersion)), boot, logging, appProperties)
def map(f: File => File) = LaunchConfiguration(scalaVersion, ivyConfiguration, app.map(f), boot.map(f), logging, appProperties)
}
final case class IvyOptions(ivyHome: Option[File], classifiers: Classifiers, repositories: List[xsbti.Repository], checksums: List[String])

View File

@ -33,8 +33,11 @@ sealed trait UpdateTarget { def tpe: String; def classifiers: List[String] }
final class UpdateScala(val classifiers: List[String]) extends UpdateTarget { def tpe = "scala" }
final class UpdateApp(val id: Application, val classifiers: List[String], val tpe: String) extends UpdateTarget
final class UpdateConfiguration(val bootDirectory: File, val ivyHome: Option[File], val scalaVersion: Option[String], val repositories: List[xsbti.Repository], val checksums: List[String]) {
def getScalaVersion = scalaVersion match { case Some(sv) => sv; case None => "" }
final class UpdateConfiguration(val bootDirectory: File, val ivyHome: Option[File], val scalaOrg: String,
val scalaVersion: Option[String], val repositories: List[xsbti.Repository], val checksums: List[String]) {
def getScalaVersion = scalaVersion match { case Some(sv) => sv; case None => "" }
}
final class UpdateResult(val success: Boolean, val scalaVersion: Option[String])
@ -42,7 +45,7 @@ final class UpdateResult(val success: Boolean, val scalaVersion: Option[String])
/** Ensures that the Scala and application jars exist for the given versions or else downloads them.*/
final class Update(config: UpdateConfiguration)
{
import config.{bootDirectory, checksums, getScalaVersion, ivyHome, repositories, scalaVersion}
import config.{bootDirectory, checksums, getScalaVersion, ivyHome, repositories, scalaVersion, scalaOrg}
bootDirectory.mkdirs
private def logFile = new File(bootDirectory, UpdateLogName)
@ -127,11 +130,12 @@ final class Update(config: UpdateConfiguration)
target match
{
case u: UpdateScala =>
val scalaVersion = getScalaVersion
addDependency(moduleID, ScalaOrg, CompilerModuleName, scalaVersion, "default;optional(default)", u.classifiers)
addDependency(moduleID, ScalaOrg, LibraryModuleName, scalaVersion, "default", u.classifiers)
val scalaVersion = getScalaVersion
addDependency(moduleID, scalaOrg, CompilerModuleName, scalaVersion, "default;optional(default)", u.classifiers)
addDependency(moduleID, scalaOrg, LibraryModuleName, scalaVersion, "default", u.classifiers)
excludeJUnit(moduleID)
System.out.println("Getting Scala " + scalaVersion + " " + reason + "...")
val scalaOrgString = if (scalaOrg != ScalaOrg) " " + scalaOrg else ""
System.out.println("Getting" + scalaOrgString + " Scala " + scalaVersion + " " + reason + "...")
case u: UpdateApp =>
val app = u.id
val resolvedName = (app.crossVersioned, scalaVersion) match {
@ -239,7 +243,7 @@ final class Update(config: UpdateConfiguration)
val filter = (a: IArtifact) => retrieveType(a.getType) && a.getExtraAttribute("classifier") == null && extraFilter(a)
retrieveOptions.setArtifactFilter(new ArtifactFilter(filter))
val scalaV = strictOr(scalaVersion, autoScalaVersion)
retrieveEngine.retrieve(module.getModuleRevisionId, baseDirectoryName(scalaV) + "/" + pattern, retrieveOptions)
retrieveEngine.retrieve(module.getModuleRevisionId, baseDirectoryName(scalaOrg, scalaV) + "/" + pattern, retrieveOptions)
}
private[this] def notCoreScala(a: IArtifact) = a.getName match {
case LibraryModuleName | CompilerModuleName => false

View File

@ -7,6 +7,7 @@ public interface Launcher
public static final int InterfaceVersion = 1;
public ScalaProvider getScala(String version);
public ScalaProvider getScala(String version, String reason);
public ScalaProvider getScala(String version, String reason, String scalaOrg);
public AppProvider app(ApplicationID id, String version);
public ClassLoader topLoader();
public GlobalLock globalLock();

View File

@ -52,6 +52,7 @@ object Defaults extends BuildCommon
))
def globalCore: Seq[Setting[_]] = inScope(GlobalScope)(defaultTestTasks(test) ++ defaultTestTasks(testOnly) ++ defaultTestTasks(testQuick) ++ Seq(
crossVersion :== CrossVersion.Disabled,
scalaOrganization :== ScalaArtifacts.Organization,
buildDependencies <<= buildDependencies or Classpaths.constructBuildDependencies,
taskTemporaryDirectory := IO.createTemporaryDirectory,
onComplete <<= taskTemporaryDirectory { dir => () => IO.delete(dir); IO.createDirectory(dir) },
@ -264,10 +265,10 @@ object Defaults extends BuildCommon
}
}
}
def scalaInstanceSetting = (appConfiguration, scalaVersion, scalaHome) map { (app, version, home) =>
def scalaInstanceSetting = (appConfiguration, scalaOrganization, scalaVersion, scalaHome) map { (app, org, version, home) =>
val launcher = app.provider.scalaProvider.launcher
home match {
case None => ScalaInstance(version, launcher)
case None => ScalaInstance(org, version, launcher)
case Some(h) => ScalaInstance(h, launcher)
}
}

View File

@ -135,6 +135,7 @@ object Keys
val compileInputs = TaskKey[Compiler.Inputs]("compile-inputs", "Collects all inputs needed for compilation.", DTask)
val scalaHome = SettingKey[Option[File]]("scala-home", "If Some, defines the local Scala installation to use for compilation, running, and testing.", ASetting)
val scalaInstance = TaskKey[ScalaInstance]("scala-instance", "Defines the Scala instance to use for compilation, running, and testing.", DTask)
val scalaOrganization = SettingKey[String]("scala-organization", "Organization/group ID of the Scala used in the project. Default value is 'org.scala-lang'. This is an advanced setting used for clones of the Scala Language. It should be disregarded in standard use cases.", CSetting)
val scalaVersion = SettingKey[String]("scala-version", "The version of Scala used for building.", APlusSetting)
val scalaBinaryVersion = SettingKey[String]("scala-binary-version", "The Scala version substring describing binary compatibility.", BPlusSetting)
val crossScalaVersions = SettingKey[Seq[String]]("cross-scala-versions", "The versions of Scala used when cross-building.", BPlusSetting)

View File

@ -21,7 +21,19 @@ final class ScalaInstance(val version: String, val loader: ClassLoader, val libr
}
object ScalaInstance
{
val ScalaOrg = "org.scala-lang"
val VersionPrefix = "version "
def apply(org: String, version: String, launcher: xsbti.Launcher): ScalaInstance =
// Due to incompatibility with previous launchers if scalaOrg has default value revert to an existing method
if (org == ScalaOrg)
apply(version, launcher)
else try {
apply(version, launcher.getScala(version, "", org))
} catch {
case x: NoSuchMethodError => error("Incompatible version of the xsbti.Launcher interface. Use sbt-0.12.x launcher instead.")
}
/** Creates a ScalaInstance using the given provider to obtain the jars and loader.*/
def apply(version: String, launcher: xsbti.Launcher): ScalaInstance =
apply(version, launcher.getScala(version))