From 182b7c655f475d72fe00a04b241ca4749335da1a Mon Sep 17 00:00:00 2001 From: Vojin Jovanovic Date: Wed, 4 Apr 2012 19:06:55 +0200 Subject: [PATCH] Adding `scalaOrg` setting key for scala clones. Adding scalaOrg key that specifies organization (artifactId) of scala used in the project. The change does not affect version checks for dependecies and LauncherConfiguration. Modified scalaProvider cache in Launcher to use (scalaOrg, version) as a key. Downloaded jars are stored in the folder scala-.../lig- if scalaOrg is not default. scala-org is an advanced setting so it can not be used in build.sbt. --- launch/BootConfiguration.scala | 20 ++++++++-- launch/Launch.scala | 39 +++++++++---------- launch/LaunchConfiguration.scala | 2 + launch/Update.scala | 16 +++++--- .../src/main/java/xsbti/Launcher.java | 1 + main/Defaults.scala | 5 ++- main/Keys.scala | 1 + util/classpath/ScalaInstance.scala | 3 ++ 8 files changed, 56 insertions(+), 31 deletions(-) diff --git a/launch/BootConfiguration.scala b/launch/BootConfiguration.scala index 3409d55d9..247475cca 100644 --- a/launch/BootConfiguration.scala +++ b/launch/BootConfiguration.scala @@ -53,11 +53,22 @@ private object BootConfiguration val DefaultIvyConfiguration = "default" - /** The name of the directory within the boot directory to retrieve scala to. */ - val ScalaDirectoryName = "lib" + private val ScalaDirectoryName = "lib" + + /** The name of the directory within the boot directory to retrieve scala to. + * scalaOrg is appended if non-standard scala is used. + * + * The reason for this inconsistency is backward compatiblity and + * relatively infrequent use of non-standard scalaOrg */ + def scalaDirectoryName(scalaOrg: String) = scalaOrg match { + case ScalaOrg => ScalaDirectoryName + case _ => ScalaDirectoryName + "-" + scalaOrg + } + /** 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. */ - val scalaRetrievePattern = ScalaDirectoryName + "/[artifact](-[classifier]).[ext]" + * containing all jars for the requested version of scala. + */ + def scalaRetrievePattern(scalaOrg: String) = scalaDirectoryName(scalaOrg) + "/[artifact](-[classifier]).[ext]" def artifactType(classifier: String) = classifier match @@ -80,6 +91,7 @@ private object BootConfiguration case None => "other" case Some(sv) => ScalaDirPrefix + sv } + def extractScalaVersion(dir: File): Option[String] = { val name = dir.getName diff --git a/launch/Launch.scala b/launch/Launch.scala index c7e6d64ba..b1385586f 100644 --- a/launch/Launch.scala +++ b/launch/Launch.scala @@ -77,18 +77,17 @@ 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} 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(BootConfiguration.ScalaOrg, version, reason) + def getScala(scalaOrg: String, version: String, reason: 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,7 +101,7 @@ 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 configuration = makeConfiguration(None, None) val jnaHome = appDirectory(new File(bootDirectory, baseDirectoryName(None)), id) val module = appModule(id, None, false, "jna") def makeLoader(): ClassLoader = { @@ -129,8 +128,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: Option[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) }) @@ -149,7 +148,7 @@ class Launch private[xsbt](val bootDirectory: File, val lockBoot: Boolean, val i retrieve() else existing(app, explicitScalaVersion, baseDirs) getOrElse retrieve() - + val scalaVersion = getOrError(strictOr(explicitScalaVersion, retrievedApp.detectedScalaVersion), "No Scala version specified or detected") val scalaProvider = getScala(scalaVersion, "(for " + id.name + ")") @@ -170,13 +169,13 @@ 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) @@ -219,10 +218,10 @@ 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 libDirectory = new File(scalaHome, ScalaDirectoryName) + val libDirectory = new File(scalaHome, scalaDirectoryName(scalaOrg)) (scalaHome, libDirectory) } @@ -257,13 +256,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(None, 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(Some(org), Some(version)), target = new UpdateScala(Value.get(classifiers.forScala)), failLabel = "Scala " + version, extraClasspath = array() diff --git a/launch/LaunchConfiguration.scala b/launch/LaunchConfiguration.scala index d1e150d1a..625ad630d 100644 --- a/launch/LaunchConfiguration.scala +++ b/launch/LaunchConfiguration.scala @@ -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]) diff --git a/launch/Update.scala b/launch/Update.scala index df20f6d36..8844e86e9 100644 --- a/launch/Update.scala +++ b/launch/Update.scala @@ -33,8 +33,13 @@ 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]) { +final class UpdateConfiguration(val bootDirectory: File, val ivyHome: Option[File], val scalaOrg: Option[String], + val scalaVersion: Option[String], val repositories: List[xsbti.Repository], val checksums: List[String]) { + def getScalaVersion = scalaVersion match { case Some(sv) => sv; case None => "" } + + def getScalaOrg = scalaOrg match { case Some(so) => so; case None => ScalaOrg } + } final class UpdateResult(val success: Boolean, val scalaVersion: Option[String]) @@ -42,7 +47,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, getScalaOrg} bootDirectory.mkdirs private def logFile = new File(bootDirectory, UpdateLogName) @@ -128,8 +133,9 @@ final class Update(config: UpdateConfiguration) { 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 scalaOrg = getScalaOrg + 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 + "...") case u: UpdateApp => @@ -233,7 +239,7 @@ final class Update(config: UpdateConfiguration) val (pattern, extraFilter) = target match { - case _: UpdateScala => (scalaRetrievePattern, const(true)) + case _: UpdateScala => (scalaRetrievePattern(getScalaOrg), const(true)) case u: UpdateApp => (appRetrievePattern(u.id.toID), notCoreScala _) } val filter = (a: IArtifact) => retrieveType(a.getType) && a.getExtraAttribute("classifier") == null && extraFilter(a) diff --git a/launch/interface/src/main/java/xsbti/Launcher.java b/launch/interface/src/main/java/xsbti/Launcher.java index 0593db35d..b21859135 100644 --- a/launch/interface/src/main/java/xsbti/Launcher.java +++ b/launch/interface/src/main/java/xsbti/Launcher.java @@ -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 scalaOrg, String version, String reason); public AppProvider app(ApplicationID id, String version); public ClassLoader topLoader(); public GlobalLock globalLock(); diff --git a/main/Defaults.scala b/main/Defaults.scala index 7d835ddd2..5216c63d6 100755 --- a/main/Defaults.scala +++ b/main/Defaults.scala @@ -52,6 +52,7 @@ object Defaults extends BuildCommon )) def globalCore: Seq[Setting[_]] = inScope(GlobalScope)(defaultTestTasks(test) ++ defaultTestTasks(testOnly) ++ defaultTestTasks(testQuick) ++ Seq( crossVersion :== CrossVersion.Disabled, + scalaOrg :== "org.scala-lang", 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, scalaOrg, scalaVersion, scalaHome) map { (app, scalaOrg, version, home) => val launcher = app.provider.scalaProvider.launcher home match { - case None => ScalaInstance(version, launcher) + case None => ScalaInstance(scalaOrg, version, launcher) case Some(h) => ScalaInstance(h, launcher) } } diff --git a/main/Keys.scala b/main/Keys.scala index 52a79757c..007f96655 100644 --- a/main/Keys.scala +++ b/main/Keys.scala @@ -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 scalaOrg = SettingKey[String]("scala-org", "Artifact id of Scala scala used in the project.", 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) diff --git a/util/classpath/ScalaInstance.scala b/util/classpath/ScalaInstance.scala index de6cabc24..b7594232d 100644 --- a/util/classpath/ScalaInstance.scala +++ b/util/classpath/ScalaInstance.scala @@ -22,6 +22,9 @@ final class ScalaInstance(val version: String, val loader: ClassLoader, val libr object ScalaInstance { val VersionPrefix = "version " + + def apply(org: String, version: String, launcher: xsbti.Launcher): ScalaInstance = + apply(version, launcher.getScala(org, version, "")) /** 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))