-
Notifications
You must be signed in to change notification settings - Fork 26
/
GlobalPlugin.scala
72 lines (69 loc) · 3.32 KB
/
GlobalPlugin.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package sbt
import Load._
import Project._
import Scoped._
import Keys._
import Configurations.Runtime
import java.io.File
import org.apache.ivy.core.module.{descriptor, id}
import descriptor.ModuleDescriptor, id.ModuleRevisionId
object GlobalPlugin
{
// constructs a sequence of settings that may be appended to a project's settings to
// statically add the global plugin as a classpath dependency.
// static here meaning that the relevant tasks for the global plugin have already been evaluated
def inject(gp: GlobalPluginData): Seq[Setting[_]] =
Seq[Setting[_]](
projectDescriptors ~= { _ ++ gp.descriptors },
projectDependencies ++= gp.projectID +: gp.dependencies,
resolvers <<= resolvers { rs => (rs ++ gp.resolvers).distinct },
internalDependencyClasspath in Runtime ~= { prev => (prev ++ gp.internalClasspath).distinct }
)
def build(base: File, s: State, config: LoadBuildConfiguration): (BuildStructure, State) =
{
val globalConfig = config.copy(injectSettings = config.injectSettings.copy(global = config.injectSettings.global ++ globalPluginSettings))
val (eval, structure) = Load(base, s, globalConfig)
val session = Load.initialSession(structure, eval)
(structure, Project.setProject(session, structure, s))
}
def load(base: File, s: State, config: LoadBuildConfiguration): GlobalPlugin =
{
val (structure, state) = build(base, s, config)
val (newS, data) = extract(state, structure)
Project.runUnloadHooks(newS) // discard state
GlobalPlugin(data, structure, inject(data), base)
}
def extract(state: State, structure: BuildStructure): (State, GlobalPluginData) =
{
import structure.{data, root, rootProject}
val p: Scope = Scope.GlobalScope in ProjectRef(root, rootProject(root))
val taskInit = (projectID, projectDependencies, projectDescriptors, resolvers, fullClasspath in Runtime, internalDependencyClasspath in Runtime, exportedProducts in Runtime, ivyModule) map {
(pid, pdeps, pdescs, rs, cp, intcp, prods, mod) =>
val depMap = pdescs + mod.dependencyMapping(state.log)
GlobalPluginData(pid, pdeps, depMap, rs, cp, prods ++ intcp)
}
val resolvedTaskInit = taskInit mapReferenced Project.mapScope(Scope replaceThis p)
val task = resolvedTaskInit evaluate data
val roots = resolvedTaskInit.dependencies
evaluate(state, structure, task, roots)
}
def evaluate[T](state: State, structure: BuildStructure, t: Task[T], roots: Seq[ScopedKey[_]]): (State, T) =
{
import EvaluateTask._
withStreams(structure, state) { str =>
val nv = nodeView(state, str, roots)
val config = EvaluateTask.defaultConfig(Project.extract(state), structure)
val (newS, result) = runTask(t, state, str, structure.index.triggers, config)(nv)
(newS, processResult(result, newS.log))
}
}
val globalPluginSettings = inScope(Scope.GlobalScope in LocalRootProject)(Seq(
organization := SbtArtifacts.Organization,
onLoadMessage <<= Keys.baseDirectory("Loading global plugins from " + _),
name := "global-plugin",
sbtPlugin := true,
version := "0.0"
))
}
final case class GlobalPluginData(projectID: ModuleID, dependencies: Seq[ModuleID], descriptors: Map[ModuleRevisionId, ModuleDescriptor], resolvers: Seq[Resolver], fullClasspath: Classpath, internalClasspath: Classpath)
final case class GlobalPlugin(data: GlobalPluginData, structure: BuildStructure, inject: Seq[Setting[_]], base: File)