Load global plugins in their own class loader and replace the base loader with that. Fixes #272.

Also, replace the base classpath with the global classpath.
This commit is contained in:
Mark Harrah
2013-03-06 10:19:18 -05:00
parent cd7afef797
commit 3fccd4cbb9
8 changed files with 65 additions and 10 deletions
+19 -7
View File
@@ -74,15 +74,26 @@ object Load
}
def buildGlobalSettings(base: File, files: Seq[File], config: LoadBuildConfiguration): ClassLoader => Seq[Setting[_]] =
{
val eval = mkEval(data(config.globalPluginClasspath), base, defaultEvalOptions)
val eval = mkEval(data(config.classpath), base, defaultEvalOptions)
val imports = baseImports ++ importAllRoot(config.globalPluginNames)
EvaluateConfigurations(eval, files, imports)
}
def loadGlobal(state: State, base: File, global: File, config: LoadBuildConfiguration): LoadBuildConfiguration =
if(base != global && global.exists)
config.copy(globalPlugin = Some(GlobalPlugin.load(global, state, config)))
else
if(base != global && global.exists) {
val gp = GlobalPlugin.load(global, state, config)
val pm = setGlobalPluginLoader(gp, config.pluginManagement)
val cp = (gp.data.fullClasspath ++ config.classpath).distinct
config.copy(globalPlugin = Some(gp), pluginManagement = pm, classpath = cp)
} else
config
private[this] def setGlobalPluginLoader(gp: GlobalPlugin, pm: PluginManagement): PluginManagement =
{
val newLoader = ClasspathUtilities.toLoader(Build.data(gp.data.fullClasspath), pm.initialLoader)
pm.copy(initialLoader = newLoader)
}
def defaultDelegates: LoadedBuild => Scope => Seq[Scope] = (lb: LoadedBuild) => {
val rootProject = getRootProject(lb.units)
def resolveRef(project: Reference): ResolvedReference = Scope.resolveReference(lb.root, rootProject, project)
@@ -482,7 +493,7 @@ object Load
!(dir * -GlobFilter(DefaultTargetName)).get.isEmpty
}
def noPlugins(dir: File, config: LoadBuildConfiguration): LoadedPlugins =
loadPluginDefinition(dir, config, PluginData(config.globalPluginClasspath, None, None))
loadPluginDefinition(dir, config, PluginData(config.classpath, None, None))
def buildPlugins(dir: File, s: State, config: LoadBuildConfiguration): LoadedPlugins =
loadPluginDefinition(dir, config, buildPluginDefinition(dir, s, config))
@@ -700,8 +711,9 @@ object Load
pluginManagement: PluginManagement, injectSettings: InjectSettings, globalPlugin: Option[GlobalPlugin], extraBuilds: Seq[URI],
log: Logger)
{
lazy val (globalPluginClasspath, globalPluginLoader) = pluginDefinitionLoader(this, Load.globalPluginClasspath(globalPlugin))
lazy val globalPluginNames = if(globalPluginClasspath.isEmpty) Nil else getPluginNames(globalPluginClasspath, globalPluginLoader)
lazy val globalPluginClasspath: Seq[Attributed[File]] = classpath
lazy val globalPluginLoader: ClassLoader = pluginManagement.initialLoader
lazy val globalPluginNames: Seq[String] = if(classpath.isEmpty) Nil else Load.getPluginNames(classpath, pluginManagement.initialLoader)
}
final case class InjectSettings(global: Seq[Setting[_]], project: Seq[Setting[_]], projectLoaded: ClassLoader => Seq[Setting[_]])
@@ -0,0 +1,4 @@
# tests that a source file in $sbt.global.base/plugins/ is available to the build definition in project/
# dummy to ensure project gets loaded
> name
@@ -0,0 +1,21 @@
import sbt._
import sbt.Keys._
object MyBuild extends Build {
lazy val mySettings = Defaults.defaultSettings ++ Seq(
name := "my-test-proj",
organization := "com.example",
check <<= update map checkVersion,
version := "0.1.0-SNAPSHOT")
lazy val proj = Project("my-test-proj", file("."), settings = mySettings)
lazy val check = TaskKey[Unit]("check", "Verifies that the junit dependency has the older version (4.5)")
def checkVersion(report: UpdateReport) {
for(mod <- report.allModules) {
if(mod.name == "junit") assert(mod.revision == "4.5", "JUnit version (%s) was not overridden".format(mod.revision))
}
}
}
@@ -0,0 +1,3 @@
// use a small java library instead of a plugin to avoid incompatibilities when upgrading
// use an old version to check that it will override a newer version in a build definition
libraryDependencies += "junit" % "junit" % "4.5"
@@ -0,0 +1,2 @@
// the version should be overridden by the global plugin
libraryDependencies += "junit" % "junit" % "4.8"
+16 -3
View File
@@ -1,4 +1,17 @@
# tests that a source file in $sbt.global.base/plugins/ is available to the build definition in project/
$ copy-file changes/Build.scala project/Build.scala
> reload
# dummy to ensure project gets loaded
> name
# ensure that a new global dependency gets picked up
$ copy-file changes/global-plugins.sbt global/plugins/plugins.sbt
> reload
# check that the class can be loaded
> eval Class.forName("org.junit.Test")
# check that it is on the classpath
> eval (x => ()) : (org.junit.Test => Unit)
# ensure that the global plugin version overrides the local version
$ copy-file changes/plugins.sbt project/plugins.sbt
> reload
> check