diff --git a/main/Build.scala b/main/Build.scala index d0448136c..d985a70f7 100644 --- a/main/Build.scala +++ b/main/Build.scala @@ -9,7 +9,7 @@ package sbt import complete.DefaultParsers.validID import Compiler.Compilers import Project.{ScopedKey, Setting} - import Keys.{globalBaseDirectory, Streams} + import Keys.{globalBaseDirectory, globalPluginsDirectory, globalSettingsDirectory, stagingDirectory, Streams} import Scope.GlobalScope import scala.annotation.tailrec @@ -267,15 +267,28 @@ object BuildPaths { import Path._ - def getGlobalBase(state: State): File = state get globalBaseDirectory orElse systemGlobalBase getOrElse defaultGlobalBase - def systemGlobalBase: Option[File] = Option(System.getProperty(GlobalBaseProperty)) flatMap { path => + def getGlobalBase(state: State): File = + getFileSetting(globalBaseDirectory, GlobalBaseProperty, defaultGlobalBase)(state) + + def getStagingDirectory(state: State, globalBase: File): File = + getFileSetting(stagingDirectory, StagingProperty, defaultStaging(globalBase))(state) + + def getGlobalPluginsDirectory(state: State, globalBase: File): File = + getFileSetting(globalPluginsDirectory, GlobalPluginsProperty, defaultGlobalPlugins(globalBase))(state) + + def getGlobalSettingsDirectory(state: State, globalBase: File): File = + getFileSetting(globalSettingsDirectory, GlobalSettingsProperty, globalBase)(state) + + def getFileSetting(stateKey: AttributeKey[File], property: String, default: File)(state: State): File = + state get stateKey orElse getFileProperty(property) getOrElse default + + def getFileProperty(name: String): Option[File] = Option(System.getProperty(name)) flatMap { path => if(path.isEmpty) None else Some(new File(path)) } def defaultGlobalBase = Path.userHome / ConfigDirectoryName - def defaultStaging(globalBase: File) = globalBase / "staging" - def defaultGlobalPlugins(globalBase: File) = globalBase / PluginsDirectoryName - def defaultGlobalSettings(globalBase: File) = configurationSources(globalBase) + private[this] def defaultStaging(globalBase: File) = globalBase / "staging" + private[this] def defaultGlobalPlugins(globalBase: File) = globalBase / PluginsDirectoryName def definitionSources(base: File): Seq[File] = (base * "*.scala").get def configurationSources(base: File): Seq[File] = (base * (GlobFilter("*.sbt") - ".sbt")).get @@ -303,6 +316,9 @@ object BuildPaths final val DefaultTargetName = "target" final val ConfigDirectoryName = ".sbt" final val GlobalBaseProperty = "sbt.global.base" + final val StagingProperty = "sbt.global.staging" + final val GlobalPluginsProperty = "sbt.global.plugins" + final val GlobalSettingsProperty = "sbt.global.settings" def crossPath(base: File, instance: ScalaInstance): File = base / ("scala_" + instance.version) } diff --git a/main/Keys.scala b/main/Keys.scala index cd2ba855b..c3e767ab9 100644 --- a/main/Keys.scala +++ b/main/Keys.scala @@ -70,6 +70,9 @@ object Keys // Path Keys val baseDirectory = SettingKey[File]("base-directory", "The base directory. Depending on the scope, this is the base directory for the build, project, configuration, or task.") val globalBaseDirectory = AttributeKey[File]("global-base-directory", "The base directory for global sbt configuration and staging.") + val globalPluginsDirectory = AttributeKey[File]("global-plugins-directory", "The base directory for global sbt plugins.") + val globalSettingsDirectory = AttributeKey[File]("global-settings-directory", "The base directory for global sbt settings.") + val stagingDirectory = AttributeKey[File]("staging-directory", "The directory for staging remote projects.") val target = SettingKey[File]("target", "Main directory for files generated by the build.") val crossTarget = SettingKey[File]("cross-target", "Main directory for files generated by the build that are cross-built.") diff --git a/main/Load.scala b/main/Load.scala index ef3c3b73d..4a7d7c989 100644 --- a/main/Load.scala +++ b/main/Load.scala @@ -29,7 +29,7 @@ object Load // note that there is State passed in but not pulled out def defaultLoad(state: State, baseDirectory: File, log: Logger): (() => Eval, BuildStructure) = { - val globalBase = BuildPaths.getGlobalBase(state) + val globalBase = getGlobalBase(state) val base = baseDirectory.getCanonicalFile val definesClass = FileValueCache(Locate.definesClass _) val rawConfig = defaultPreGlobal(state, base, definesClass.get, globalBase, log) @@ -42,7 +42,7 @@ object Load { val provider = state.configuration.provider val scalaProvider = provider.scalaProvider - val stagingDirectory = defaultStaging(globalBase).getCanonicalFile + val stagingDirectory = getStagingDirectory(state, globalBase).getCanonicalFile val loader = getClass.getClassLoader val classpath = Attributed.blankSeq(provider.mainClasspath ++ scalaProvider.jars) val compilers = Compiler.compilers(ClasspathOptions.boot)(state.configuration, log) @@ -56,8 +56,10 @@ object Load EvaluateTask.injectSettings def defaultWithGlobal(state: State, base: File, rawConfig: LoadBuildConfiguration, globalBase: File, log: Logger): LoadBuildConfiguration = { - val withGlobal = loadGlobal(state, base, defaultGlobalPlugins(globalBase), rawConfig) - loadGlobalSettings(base, globalBase, defaultGlobalSettings(globalBase), withGlobal) + val globalPluginsDir = getGlobalPluginsDirectory(state, globalBase) + val withGlobal = loadGlobal(state, base, globalPluginsDir, rawConfig) + val globalSettings = configurationSources(getGlobalSettingsDirectory(state, globalBase)) + loadGlobalSettings(base, globalBase, globalSettings, withGlobal) } def loadGlobalSettings(base: File, globalBase: File, files: Seq[File], config: LoadBuildConfiguration): LoadBuildConfiguration =