From 182b7c655f475d72fe00a04b241ca4749335da1a Mon Sep 17 00:00:00 2001 From: Vojin Jovanovic Date: Wed, 4 Apr 2012 19:06:55 +0200 Subject: [PATCH 1/5] 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)) From 0f6a50daee448240c15d5894b203d57fc58df69c Mon Sep 17 00:00:00 2001 From: Vojin Jovanovic Date: Thu, 5 Apr 2012 12:19:49 +0200 Subject: [PATCH 2/5] Addressing https://github.com/harrah/xsbt/pull/418 Changed the order of parameters in getScala method. Changed the key name to scalaOrganization (scala-organization). Augmented description of the key. Minor fixes. --- launch/Launch.scala | 8 +++++--- launch/interface/src/main/java/xsbti/Launcher.java | 2 +- main/Defaults.scala | 6 +++--- main/Keys.scala | 2 +- util/classpath/ScalaInstance.scala | 2 +- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/launch/Launch.scala b/launch/Launch.scala index b1385586f..d4ff7d161 100644 --- a/launch/Launch.scala +++ b/launch/Launch.scala @@ -84,10 +84,12 @@ class Launch private[xsbt](val bootDirectory: File, val lockBoot: Boolean, val i bootDirectory.mkdirs 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 = getScala(BootConfiguration.ScalaOrg, version, reason) - def getScala(scalaOrg: String, version: String, reason: String) = scalaProviders((scalaOrg, version), reason) + def getScala(version: String, reason: String): xsbti.ScalaProvider = getScala(version, reason, BootConfiguration.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) diff --git a/launch/interface/src/main/java/xsbti/Launcher.java b/launch/interface/src/main/java/xsbti/Launcher.java index b21859135..f3b16214f 100644 --- a/launch/interface/src/main/java/xsbti/Launcher.java +++ b/launch/interface/src/main/java/xsbti/Launcher.java @@ -7,7 +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 ScalaProvider getScala(String version, String reason, String scalaOrg); public AppProvider app(ApplicationID id, String version); public ClassLoader topLoader(); public GlobalLock globalLock(); diff --git a/main/Defaults.scala b/main/Defaults.scala index 5216c63d6..47ea04796 100755 --- a/main/Defaults.scala +++ b/main/Defaults.scala @@ -52,7 +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", + scalaOrganization :== ScalaArtifacts.Organization, buildDependencies <<= buildDependencies or Classpaths.constructBuildDependencies, taskTemporaryDirectory := IO.createTemporaryDirectory, onComplete <<= taskTemporaryDirectory { dir => () => IO.delete(dir); IO.createDirectory(dir) }, @@ -265,10 +265,10 @@ object Defaults extends BuildCommon } } } - def scalaInstanceSetting = (appConfiguration, scalaOrg, scalaVersion, scalaHome) map { (app, scalaOrg, version, home) => + def scalaInstanceSetting = (appConfiguration, scalaOrganization, scalaVersion, scalaHome) map { (app, org, version, home) => val launcher = app.provider.scalaProvider.launcher home match { - case None => ScalaInstance(scalaOrg, version, launcher) + case None => ScalaInstance(org, version, launcher) case Some(h) => ScalaInstance(h, launcher) } } diff --git a/main/Keys.scala b/main/Keys.scala index 007f96655..80309c6d3 100644 --- a/main/Keys.scala +++ b/main/Keys.scala @@ -135,7 +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 scalaOrganization = SettingKey[String]("scala-organization", "Organization/group ID of the Scala used in the project. Default value is 'org.scala-lang'.", 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 b7594232d..374d9070d 100644 --- a/util/classpath/ScalaInstance.scala +++ b/util/classpath/ScalaInstance.scala @@ -24,7 +24,7 @@ object ScalaInstance val VersionPrefix = "version " def apply(org: String, version: String, launcher: xsbti.Launcher): ScalaInstance = - apply(version, launcher.getScala(org, version, "")) + apply(version, launcher.getScala(version, "", org)) /** 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)) From f17cb88d00070532d9d1b9adc26191eff46b617e Mon Sep 17 00:00:00 2001 From: Vojin Jovanovic Date: Tue, 10 Apr 2012 12:12:04 +0200 Subject: [PATCH 3/5] Augmenting scalaOrganization key description. --- main/Keys.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/Keys.scala b/main/Keys.scala index 80309c6d3..b9e677263 100644 --- a/main/Keys.scala +++ b/main/Keys.scala @@ -135,7 +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'.", CSetting) + 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) From cbb8caef0c757288f8df74459a696cfe46bb6aba Mon Sep 17 00:00:00 2001 From: Vojin Jovanovic Date: Wed, 11 Apr 2012 04:04:21 +0200 Subject: [PATCH 4/5] Backwards compatibility check for getScala method. Added groupId dependant baseDirectoryName. General code cleanup. --- launch/BootConfiguration.scala | 25 +++++++++-------------- launch/Launch.scala | 32 +++++++++++++++--------------- launch/Update.scala | 17 +++++++--------- util/classpath/ScalaInstance.scala | 10 +++++++++- 4 files changed, 41 insertions(+), 43 deletions(-) diff --git a/launch/BootConfiguration.scala b/launch/BootConfiguration.scala index 247475cca..5b835ceec 100644 --- a/launch/BootConfiguration.scala +++ b/launch/BootConfiguration.scala @@ -53,22 +53,12 @@ private object BootConfiguration val DefaultIvyConfiguration = "default" - 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 - } + 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. */ - def scalaRetrievePattern(scalaOrg: String) = scalaDirectoryName(scalaOrg) + "/[artifact](-[classifier]).[ext]" + val scalaRetrievePattern = ScalaDirectoryName + "/[artifact](-[classifier]).[ext]" def artifactType(classifier: String) = classifier match @@ -82,20 +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) => 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 diff --git a/launch/Launch.scala b/launch/Launch.scala index d4ff7d161..3bcc59ccd 100644 --- a/launch/Launch.scala +++ b/launch/Launch.scala @@ -77,14 +77,14 @@ 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), 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 = getScala(version, reason, BootConfiguration.ScalaOrg) + 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 = @@ -103,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, 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))) @@ -130,7 +130,7 @@ class Launch private[xsbt](val bootDirectory: File, val lockBoot: Boolean, val i module.retrieveCorrupt(missing) } - private[this] def makeConfiguration(scalaOrg: Option[String], version: Option[String]): UpdateConfiguration = + 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 = @@ -143,13 +143,13 @@ 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 + ")") @@ -162,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))) @@ -183,7 +183,7 @@ class Launch private[xsbt](val bootDirectory: File, val lockBoot: Boolean, val i 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 { @@ -192,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 => @@ -222,8 +222,8 @@ class Launch private[xsbt](val bootDirectory: File, val lockBoot: Boolean, val i def scalaDirs(module: ModuleDefinition, scalaOrg: String, scalaVersion: String): (File, File) = { - val scalaHome = new File(bootDirectory, baseDirectoryName(Some(scalaVersion))) - val libDirectory = new File(scalaHome, scalaDirectoryName(scalaOrg)) + val scalaHome = new File(bootDirectory, baseDirectoryName(scalaOrg, Some(scalaVersion))) + val libDirectory = new File(scalaHome, ScalaDirectoryName) (scalaHome, libDirectory) } @@ -258,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(None, 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(org: String, version: String): ModuleDefinition = new ModuleDefinition( - configuration = makeConfiguration(Some(org), Some(version)), + configuration = makeConfiguration(org, Some(version)), target = new UpdateScala(Value.get(classifiers.forScala)), failLabel = "Scala " + version, extraClasspath = array() diff --git a/launch/Update.scala b/launch/Update.scala index 8844e86e9..767e4057d 100644 --- a/launch/Update.scala +++ b/launch/Update.scala @@ -33,12 +33,10 @@ 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 scalaOrg: Option[String], +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 => "" } - - def getScalaOrg = scalaOrg match { case Some(so) => so; case None => ScalaOrg } + def getScalaVersion = scalaVersion match { case Some(sv) => sv; case None => "" } } @@ -47,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, getScalaOrg} + import config.{bootDirectory, checksums, getScalaVersion, ivyHome, repositories, scalaVersion, scalaOrg} bootDirectory.mkdirs private def logFile = new File(bootDirectory, UpdateLogName) @@ -132,12 +130,11 @@ final class Update(config: UpdateConfiguration) target match { case u: UpdateScala => - val scalaVersion = getScalaVersion - val scalaOrg = getScalaOrg + 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 + "...") + System.out.println("Getting " + scalaOrg + " Scala " + scalaVersion + " " + reason + "...") case u: UpdateApp => val app = u.id val resolvedName = (app.crossVersioned, scalaVersion) match { @@ -239,13 +236,13 @@ final class Update(config: UpdateConfiguration) val (pattern, extraFilter) = target match { - case _: UpdateScala => (scalaRetrievePattern(getScalaOrg), const(true)) + case _: UpdateScala => (scalaRetrievePattern, const(true)) case u: UpdateApp => (appRetrievePattern(u.id.toID), notCoreScala _) } 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 diff --git a/util/classpath/ScalaInstance.scala b/util/classpath/ScalaInstance.scala index 374d9070d..84f6269f0 100644 --- a/util/classpath/ScalaInstance.scala +++ b/util/classpath/ScalaInstance.scala @@ -23,8 +23,16 @@ object ScalaInstance { val VersionPrefix = "version " - def apply(org: String, version: String, launcher: xsbti.Launcher): ScalaInstance = + def apply(org: String, version: String, launcher: xsbti.Launcher): ScalaInstance = { + // launcher compatibility check + val strClass = "".getClass + if (launcher.getClass.getMethods.exists(m => + m.getName == "getScala" && + m.getParameterTypes.toSeq == Seq(strClass, strClass, strClass))) apply(version, launcher.getScala(version, "", org)) + else + 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)) From 079a2c1bdace480b72c9e49318b0e104a268f62a Mon Sep 17 00:00:00 2001 From: Vojin Jovanovic Date: Wed, 11 Apr 2012 12:55:01 +0200 Subject: [PATCH 5/5] Minimizing effects of scalaOrganization key addition. --- launch/BootConfiguration.scala | 8 ++++---- launch/Update.scala | 3 ++- util/classpath/ScalaInstance.scala | 21 +++++++++++---------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/launch/BootConfiguration.scala b/launch/BootConfiguration.scala index 5b835ceec..aed6c77dc 100644 --- a/launch/BootConfiguration.scala +++ b/launch/BootConfiguration.scala @@ -72,23 +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 ScalaVersionPrefix = ".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(scalaOrg: String, scalaVersion: Option[String]) = scalaVersion match { case None => "other" - case Some(sv) => scalaOrg + ScalaVersionPrefix + sv + case Some(sv) => (if (scalaOrg == ScalaOrg) "" else scalaOrg + ".") + ScalaVersionPrefix + sv } def extractScalaVersion(dir: File): Option[String] = { val name = dir.getName if(name.contains(ScalaVersionPrefix)) - Some(name.substring(name.lastIndexOf(ScalaVersionPrefix) + ScalaVersionPrefix.length)) + Some(name.substring(name.lastIndexOf(ScalaVersionPrefix) + ScalaVersionPrefix.length)) else - None + None } } private object ProxyProperties diff --git a/launch/Update.scala b/launch/Update.scala index 767e4057d..23816e467 100644 --- a/launch/Update.scala +++ b/launch/Update.scala @@ -134,7 +134,8 @@ final class Update(config: UpdateConfiguration) addDependency(moduleID, scalaOrg, CompilerModuleName, scalaVersion, "default;optional(default)", u.classifiers) addDependency(moduleID, scalaOrg, LibraryModuleName, scalaVersion, "default", u.classifiers) excludeJUnit(moduleID) - System.out.println("Getting " + scalaOrg + " 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 { diff --git a/util/classpath/ScalaInstance.scala b/util/classpath/ScalaInstance.scala index 84f6269f0..9b687c9b5 100644 --- a/util/classpath/ScalaInstance.scala +++ b/util/classpath/ScalaInstance.scala @@ -21,18 +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 = { - // launcher compatibility check - val strClass = "".getClass - if (launcher.getClass.getMethods.exists(m => - m.getName == "getScala" && - m.getParameterTypes.toSeq == Seq(strClass, strClass, strClass))) - apply(version, launcher.getScala(version, "", org)) - else - error("Incompatible version of the xsbti.Launcher interface. Use sbt-0.12.x launcher instead.") - } + 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))