From 2d342d14858e3ef3b9447cc3a03e3045f1656770 Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Tue, 12 Jul 2011 23:09:57 -0400 Subject: [PATCH] allow global sbt directory to be configured. fixes #96 --- main/Build.scala | 14 ++++++++++---- main/GlobalPlugin.scala | 4 ++-- main/Keys.scala | 1 + main/Load.scala | 30 ++++++++++++++++++++---------- 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/main/Build.scala b/main/Build.scala index 882a6241f..e28adee3b 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.Streams + import Keys.{globalBaseDirectory, Streams} import Scope.GlobalScope import scala.annotation.tailrec @@ -231,10 +231,15 @@ object BuildPaths import Path._ import GlobFilter._ - def defaultStaging = Path.userHome / ConfigDirectoryName / "staging" - def defaultGlobalPlugins = Path.userHome / ConfigDirectoryName / PluginsDirectoryName + def getGlobalBase(state: State): File = state get globalBaseDirectory orElse systemGlobalBase getOrElse defaultGlobalBase + def systemGlobalBase: Option[File] = Option(System.getProperty(GlobalBaseProperty)) flatMap { path => + if(path.isEmpty) None else Some(new File(path)) + } + def defaultGlobalBase = Path.userHome / ConfigDirectoryName - def defaultGlobalSettings = configurationSources(defaultGlobalBase) + def defaultStaging(globalBase: File) = globalBase / "staging" + def defaultGlobalPlugins(globalBase: File) = globalBase / PluginsDirectoryName + def defaultGlobalSettings(globalBase: File) = configurationSources(globalBase) def definitionSources(base: File): Seq[File] = (base * "*.scala").get def configurationSources(base: File): Seq[File] = (base * "*.sbt").get @@ -256,6 +261,7 @@ object BuildPaths final val PluginsDirectoryName = "plugins" final val DefaultTargetName = "target" final val ConfigDirectoryName = ".sbt" + final val GlobalBaseProperty = "sbt.global.base" def crossPath(base: File, instance: ScalaInstance): File = base / ("scala_" + instance.version) } diff --git a/main/GlobalPlugin.scala b/main/GlobalPlugin.scala index 97226da12..40db7ce6b 100644 --- a/main/GlobalPlugin.scala +++ b/main/GlobalPlugin.scala @@ -32,7 +32,7 @@ object GlobalPlugin { val (structure, state) = build(base, s, config) val data = extract(state, structure) - GlobalPlugin(data, structure, inject(data)) + GlobalPlugin(data, structure, inject(data), base) } def extract(state: State, structure: BuildStructure): GlobalPluginData = { @@ -63,4 +63,4 @@ object GlobalPlugin )) } final case class GlobalPluginData(projectID: ModuleID, dependencies: Seq[ModuleID], descriptors: Map[ModuleRevisionId, ModuleDescriptor], fullClasspath: Classpath, internalClasspath: Classpath) -final case class GlobalPlugin(data: GlobalPluginData, structure: BuildStructure, inject: Seq[Setting[_]]) +final case class GlobalPlugin(data: GlobalPluginData, structure: BuildStructure, inject: Seq[Setting[_]], base: File) diff --git a/main/Keys.scala b/main/Keys.scala index 606bf18b9..9d8386e9b 100644 --- a/main/Keys.scala +++ b/main/Keys.scala @@ -57,6 +57,7 @@ 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 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 d98820a05..6b47bdb55 100644 --- a/main/Load.scala +++ b/main/Load.scala @@ -24,14 +24,24 @@ object Load import BuildPaths._ import BuildStreams._ import Locate.DefinesClass - + // 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 base = baseDirectory.getCanonicalFile + val definesClass = FileValueCache(Locate.definesClass _) + val rawConfig = defaultPreGlobal(state, base, definesClass.get, globalBase, log) + val config = defaultWithGlobal(state, base, rawConfig, globalBase, log) + val result = apply(base, state, config) + definesClass.clear() + result + } + def defaultPreGlobal(state: State, baseDirectory: File, definesClass: DefinesClass, globalBase: File, log: Logger): LoadBuildConfiguration = { val provider = state.configuration.provider val scalaProvider = provider.scalaProvider - val stagingDirectory = defaultStaging.getCanonicalFile - val base = baseDirectory.getCanonicalFile + val stagingDirectory = defaultStaging(globalBase).getCanonicalFile val loader = getClass.getClassLoader val classpath = Attributed.blankSeq(provider.mainClasspath ++ scalaProvider.jars) val compilers = Compiler.compilers(ClasspathOptions.boot)(state.configuration, log) @@ -39,14 +49,14 @@ object Load val delegates = defaultDelegates val injectGlobal: Seq[Project.Setting[_]] = ((appConfiguration in GlobalScope) :== state.configuration) +: EvaluateTask.injectSettings val inject = InjectSettings(injectGlobal, Nil, const(Nil)) - val definesClass = FileValueCache(Locate.definesClass _) - val rawConfig = new LoadBuildConfiguration(stagingDirectory, classpath, loader, compilers, evalPluginDef, definesClass.get, delegates, EvaluateTask.injectStreams, inject, None, log) - val withGlobal = loadGlobal(state, baseDirectory, defaultGlobalPlugins, rawConfig) - val config = loadGlobalSettings(baseDirectory, defaultGlobalBase, defaultGlobalSettings, withGlobal) - val result = apply(base, state, config) - definesClass.clear() - result + new LoadBuildConfiguration(stagingDirectory, classpath, loader, compilers, evalPluginDef, definesClass, delegates, EvaluateTask.injectStreams, inject, None, log) } + 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) + } + def loadGlobalSettings(base: File, globalBase: File, files: Seq[File], config: LoadBuildConfiguration): LoadBuildConfiguration = { val compiled: ClassLoader => Seq[Setting[_]] =