resolve plugin dependency version conflicts according to build order, first part of fix for #329

This commit is contained in:
Mark Harrah 2012-02-14 21:59:12 -05:00
parent b0e86898d1
commit 0fbe987cd0
3 changed files with 55 additions and 6 deletions

View File

@ -123,6 +123,12 @@ final class BuildLoader(
full.setRoot(loaders.full),
loaders.transformAll andThen transformAll
)
def updatePluginManagement(overrides: Set[ModuleID], loader: ClassLoader): BuildLoader =
{
val mgmt = config.pluginManagement
val newConfig = config.copy(pluginManagement = mgmt.copy(overrides = mgmt.overrides ++ overrides, loader = loader))
new BuildLoader(fail, state, newConfig, resolvers, builders, transformer, full, transformAll)
}
def components = new Components(resolvers.applyFun, builders.applyFun, transformer, full.applyFun, transformAll)
def apply(uri: URI): BuildUnit =
{

View File

@ -48,8 +48,9 @@ object Load
val compilers = Compiler.compilers(ClasspathOptions.boot)(state.configuration, log)
val evalPluginDef = EvaluateTask.evalPluginDef(log) _
val delegates = defaultDelegates
val pluginMgmt = PluginManagement(loader)
val inject = InjectSettings(injectGlobal(state), Nil, const(Nil))
new LoadBuildConfiguration(stagingDirectory, classpath, loader, compilers, evalPluginDef, definesClass, delegates, EvaluateTask.injectStreams, inject, None, log)
new LoadBuildConfiguration(stagingDirectory, classpath, loader, compilers, evalPluginDef, definesClass, delegates, EvaluateTask.injectStreams, pluginMgmt, inject, None, log)
}
def injectGlobal(state: State): Seq[Project.Setting[_]] =
(appConfiguration in GlobalScope :== state.configuration) +:
@ -229,13 +230,14 @@ object Load
if(srcs.isEmpty) const(Nil) else EvaluateConfigurations(eval(), srcs, imports)
def load(file: File, s: State, config: LoadBuildConfiguration): PartBuild =
load(file, builtinLoader(s, config.copy(pluginManagement = config.pluginManagement.shift) ))
def builtinLoader(s: State, config: LoadBuildConfiguration): BuildLoader =
{
val fail = (uri: URI) => error("Invalid build URI (no handler available): " + uri)
val resolver = (info: BuildLoader.ResolveInfo) => RetrieveUnit(info)
val build = (info: BuildLoader.BuildInfo) => Some(() => loadUnit(info.uri, info.base, info.state, info.config))
val components = BuildLoader.components(resolver, build, full = BuildLoader.componentLoader)
val builtinLoader = BuildLoader(components, fail, s, config)
load(file, builtinLoader)
BuildLoader(components, fail, s, config)
}
def load(file: File, loaders: BuildLoader): PartBuild = loadURI(IO.directoryURI(file), loaders)
def loadURI(uri: URI, loaders: BuildLoader): PartBuild =
@ -246,6 +248,11 @@ object Load
val build = new PartBuild(uri, map)
newLoaders transformAll build
}
def addOverrides(unit: BuildUnit, loaders: BuildLoader): BuildLoader =
{
val overrides = PluginManagement.extractOverrides(unit.plugins.fullClasspath)
loaders.updatePluginManagement(overrides, unit.plugins.loader)
}
def addResolvers(unit: BuildUnit, isRoot: Boolean, loaders: BuildLoader): BuildLoader =
unit.definitions.builds.flatMap(_.buildLoaders) match
{
@ -287,7 +294,7 @@ object Load
{
val (loadedBuild, refs) = loaded(loaders(b))
checkBuildBase(loadedBuild.unit.localBase)
val newLoader = addResolvers(loadedBuild.unit, builds.isEmpty, loaders)
val newLoader = addOverrides(loadedBuild.unit, addResolvers(loadedBuild.unit, builds.isEmpty, loaders))
loadAll(refs.flatMap(Reference.uri) reverse_::: bs, references.updated(b, refs), newLoader, builds.updated(b, loadedBuild))
}
case Nil => (references, builds, loaders)
@ -428,7 +435,10 @@ object Load
Keys.onLoadMessage <<= Keys.baseDirectory("Loading project definition from " + _)
))
def enableSbtPlugin(config: LoadBuildConfiguration): LoadBuildConfiguration =
config.copy(injectSettings = config.injectSettings.copy(global = autoPluginSettings ++ config.injectSettings.global))
config.copy(injectSettings = config.injectSettings.copy(
global = autoPluginSettings ++ config.injectSettings.global,
project = config.pluginManagement.inject ++ config.injectSettings.project
))
def activateGlobalPlugin(config: LoadBuildConfiguration): LoadBuildConfiguration =
config.globalPlugin match
{
@ -624,7 +634,10 @@ object Load
val aggregates = Aggregation.relation(units)
new BuildUtil(keyIndex, data, root, Load getRootProject units, getp, configs, aggregates)
}
final case class LoadBuildConfiguration(stagingDirectory: File, classpath: Seq[Attributed[File]], loader: ClassLoader, compilers: Compilers, evalPluginDef: (BuildStructure, State) => Seq[Attributed[File]], definesClass: DefinesClass, delegates: LoadedBuild => Scope => Seq[Scope], scopeLocal: ScopeLocal, injectSettings: InjectSettings, globalPlugin: Option[GlobalPlugin], log: Logger)
final case class LoadBuildConfiguration(stagingDirectory: File, classpath: Seq[Attributed[File]], loader: ClassLoader,
compilers: Compilers, evalPluginDef: (BuildStructure, State) => Seq[Attributed[File]], definesClass: DefinesClass,
delegates: LoadedBuild => Scope => Seq[Scope], scopeLocal: ScopeLocal,
pluginManagement: PluginManagement, injectSettings: InjectSettings, globalPlugin: Option[GlobalPlugin], log: Logger)
{
lazy val (globalPluginClasspath, globalPluginLoader) = pluginDefinitionLoader(this, Load.globalPluginClasspath(globalPlugin))
lazy val globalPluginNames = if(globalPluginClasspath.isEmpty) Nil else getPluginNames(globalPluginClasspath, globalPluginLoader)

View File

@ -0,0 +1,30 @@
package sbt
import Keys.Classpath
import Project.Setting
final case class PluginManagement(overrides: Set[ModuleID], applyOverrides: Set[ModuleID], loader: ClassLoader, initialLoader: ClassLoader)
{
def shift: PluginManagement =
PluginManagement(Set.empty, overrides, initialLoader, initialLoader)
def addOverrides(os: Set[ModuleID]): PluginManagement =
copy(overrides = overrides ++ os)
def addOverrides(cp: Classpath): PluginManagement =
addOverrides(PluginManagement extractOverrides cp)
def inject: Seq[Setting[_]] = Seq(
Keys.dependencyOverrides ++= overrides
)
}
object PluginManagement
{
def apply(initialLoader: ClassLoader): PluginManagement = PluginManagement(Set.empty, Set.empty, initialLoader, initialLoader)
def extractOverrides(classpath: Classpath): Set[ModuleID] =
classpath flatMap { _.metadata get Keys.moduleID.key map keepOverrideInfo } toSet;
def keepOverrideInfo(m: ModuleID): ModuleID =
ModuleID(m.organization, m.name, m.revision, crossVersion = m.crossVersion)
}