mirror of
https://github.com/ethauvin/kobalt.git
synced 2025-04-26 08:27:12 -07:00
Refactoring of BuildScript.
This commit is contained in:
parent
947c620e56
commit
43ccceb71e
5 changed files with 246 additions and 198 deletions
|
@ -1,6 +1,7 @@
|
|||
package com.beust.kobalt.internal.remote
|
||||
|
||||
import com.beust.kobalt.Args
|
||||
import com.beust.kobalt.api.Project
|
||||
import com.beust.kobalt.internal.PluginInfo
|
||||
import com.beust.kobalt.kotlin.BuildFile
|
||||
import com.beust.kobalt.kotlin.BuildFileCompiler
|
||||
|
@ -28,16 +29,16 @@ class GetDependenciesCommand @Inject constructor(val executors: KobaltExecutors,
|
|||
val buildFile = BuildFile(Paths.get(received.get("buildFile").asString), "GetDependenciesCommand")
|
||||
val scriptCompiler = buildFileCompilerFactory.create(listOf(buildFile), pluginInfo)
|
||||
scriptCompiler.observable.subscribe {
|
||||
buildScriptInfo -> if (buildScriptInfo.projects.size > 0) {
|
||||
sender.sendData(toData(buildScriptInfo))
|
||||
projects -> if (projects.size > 0) {
|
||||
sender.sendData(toData(projects))
|
||||
}
|
||||
}
|
||||
scriptCompiler.compileBuildFiles(args)
|
||||
}
|
||||
|
||||
private fun toData(info: BuildFileCompiler.BuildScriptInfo) : CommandData {
|
||||
private fun toData(projects: List<Project>) : CommandData {
|
||||
val projectDatas = arrayListOf<ProjectData>()
|
||||
val executor = executors.miscExecutor
|
||||
val projects = arrayListOf<ProjectData>()
|
||||
|
||||
fun toDependencyData(d: IClasspathDependency, scope: String) : DependencyData {
|
||||
val dep = MavenDependency.create(d.id, executor)
|
||||
|
@ -46,7 +47,7 @@ class GetDependenciesCommand @Inject constructor(val executors: KobaltExecutors,
|
|||
|
||||
fun allDeps(l: List<IClasspathDependency>) = dependencyManager.transitiveClosure(l)
|
||||
|
||||
info.projects.forEach { project ->
|
||||
projects.forEach { project ->
|
||||
val allDependencies =
|
||||
allDeps(project.compileDependencies).map { toDependencyData(it, "compile") } +
|
||||
allDeps(project.compileProvidedDependencies).map { toDependencyData(it, "provided") } +
|
||||
|
@ -54,10 +55,10 @@ class GetDependenciesCommand @Inject constructor(val executors: KobaltExecutors,
|
|||
allDeps(project.testDependencies).map { toDependencyData(it, "testCompile") } +
|
||||
allDeps(project.testProvidedDependencies).map { toDependencyData(it, "testProvided") }
|
||||
|
||||
projects.add(ProjectData(project.name, allDependencies))
|
||||
projectDatas.add(ProjectData(project.name, allDependencies))
|
||||
}
|
||||
log(1, "Returning BuildScriptInfo")
|
||||
val result = toCommandData(Gson().toJson(GetDependenciesData(projects)))
|
||||
val result = toCommandData(Gson().toJson(GetDependenciesData(projectDatas)))
|
||||
log(2, " $result")
|
||||
return result
|
||||
}
|
||||
|
|
|
@ -3,28 +3,24 @@ package com.beust.kobalt.kotlin
|
|||
import com.beust.kobalt.Args
|
||||
import com.beust.kobalt.KobaltException
|
||||
import com.beust.kobalt.Plugins
|
||||
import com.beust.kobalt.api.*
|
||||
import com.beust.kobalt.api.annotation.Task
|
||||
import com.beust.kobalt.api.Kobalt
|
||||
import com.beust.kobalt.api.KobaltContext
|
||||
import com.beust.kobalt.api.PluginProperties
|
||||
import com.beust.kobalt.api.Project
|
||||
import com.beust.kobalt.internal.PluginInfo
|
||||
import com.beust.kobalt.kotlin.internal.BuildScriptUtil
|
||||
import com.beust.kobalt.kotlin.internal.ParsedBuildFile
|
||||
import com.beust.kobalt.kotlin.internal.VersionFile
|
||||
import com.beust.kobalt.maven.DependencyManager
|
||||
import com.beust.kobalt.misc.KFiles
|
||||
import com.beust.kobalt.misc.KobaltExecutors
|
||||
import com.beust.kobalt.misc.Topological
|
||||
import com.beust.kobalt.misc.log
|
||||
import com.beust.kobalt.plugin.kotlin.kotlinCompilePrivate
|
||||
import com.google.inject.assistedinject.Assisted
|
||||
import rx.subjects.PublishSubject
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.InputStream
|
||||
import java.lang.reflect.Modifier
|
||||
import java.net.URL
|
||||
import java.net.URLClassLoader
|
||||
import java.nio.charset.Charset
|
||||
import java.nio.file.Paths
|
||||
import java.util.*
|
||||
import java.util.jar.JarInputStream
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
|
@ -35,13 +31,13 @@ import javax.inject.Inject
|
|||
public class BuildFileCompiler @Inject constructor(@Assisted("buildFiles") val buildFiles: List<BuildFile>,
|
||||
@Assisted val pluginInfo: PluginInfo, val files: KFiles, val plugins: Plugins,
|
||||
val dependencyManager: DependencyManager, val pluginProperties: PluginProperties,
|
||||
val executors: KobaltExecutors) {
|
||||
val executors: KobaltExecutors, val buildScriptUtil: BuildScriptUtil) {
|
||||
|
||||
interface IFactory {
|
||||
fun create(@Assisted("buildFiles") buildFiles: List<BuildFile>, pluginInfo: PluginInfo) : BuildFileCompiler
|
||||
}
|
||||
|
||||
val observable = PublishSubject.create<BuildScriptInfo>()
|
||||
val observable = PublishSubject.create<List<Project>>()
|
||||
|
||||
private val SCRIPT_JAR = "buildScript.jar"
|
||||
|
||||
|
@ -65,31 +61,17 @@ public class BuildFileCompiler @Inject constructor(@Assisted("buildFiles") val b
|
|||
return allProjects
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure all the projects have a unique name.
|
||||
*/
|
||||
private fun validateProjects(projects: List<Project>) {
|
||||
val seen = hashSetOf<String>()
|
||||
projects.forEach {
|
||||
if (seen.contains(it.name)) {
|
||||
throw KobaltException("Duplicate project name: $it")
|
||||
} else {
|
||||
seen.add(it.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun findProjects(context: KobaltContext): List<Project> {
|
||||
val result = arrayListOf<Project>()
|
||||
buildFiles.forEach { buildFile ->
|
||||
val pair = processBuildFile(context, buildFile)
|
||||
val pluginUrls = pair.second
|
||||
val processBuildFile = parseBuildFile(context, buildFile)
|
||||
val pluginUrls = processBuildFile.pluginUrls
|
||||
val buildScriptJarFile = File(KFiles.findBuildScriptLocation(buildFile, SCRIPT_JAR))
|
||||
|
||||
// If the script jar files were generated by a different version, wipe them in case the API
|
||||
// changed in-between
|
||||
buildScriptJarFile.parentFile.let { dir ->
|
||||
if (! isSameVersionFile(dir)) {
|
||||
if (! VersionFile.isSameVersionFile(dir)) {
|
||||
log(1, "Detected new installation, wiping $dir")
|
||||
dir.listFiles().map { it.delete() }
|
||||
}
|
||||
|
@ -98,24 +80,20 @@ public class BuildFileCompiler @Inject constructor(@Assisted("buildFiles") val b
|
|||
// Write the modified Build.kt (e.g. maybe profiles were applied) to a temporary file,
|
||||
// compile it, jar it in buildScript.jar and run it
|
||||
val modifiedBuildFile = KFiles.createTempFile(".kt")
|
||||
KFiles.saveFile(modifiedBuildFile, pair.first.buildScriptCode)
|
||||
KFiles.saveFile(modifiedBuildFile, processBuildFile.buildScriptCode)
|
||||
maybeCompileBuildFile(context, BuildFile(Paths.get(modifiedBuildFile.path), "Modified Build.kt"),
|
||||
buildScriptJarFile, pluginUrls)
|
||||
val buildScriptInfo = runBuildScriptJarFile(buildScriptJarFile, pluginUrls)
|
||||
result.addAll(buildScriptInfo.projects)
|
||||
val projects = buildScriptUtil.runBuildScriptJarFile(buildScriptJarFile, pluginUrls, context)
|
||||
result.addAll(projects)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun isUpToDate(buildFile: BuildFile, jarFile: File) =
|
||||
buildFile.exists() && jarFile.exists()
|
||||
&& buildFile.lastModified < jarFile.lastModified()
|
||||
|
||||
private fun maybeCompileBuildFile(context: KobaltContext, buildFile: BuildFile, buildScriptJarFile: File,
|
||||
pluginUrls: List<URL>) {
|
||||
log(2, "Running build file ${buildFile.name} jar: $buildScriptJarFile")
|
||||
|
||||
if (isUpToDate(buildFile, buildScriptJarFile)) {
|
||||
if (buildScriptUtil.isUpToDate(buildFile, buildScriptJarFile)) {
|
||||
log(2, "Build file is up to date")
|
||||
} else {
|
||||
log(2, "Need to recompile ${buildFile.name}")
|
||||
|
@ -139,156 +117,12 @@ public class BuildFileCompiler @Inject constructor(@Assisted("buildFiles") val b
|
|||
* - the source code for the modified Build.kt (after profiles are applied)
|
||||
* - the URL's of all the plug-ins that were found.
|
||||
*/
|
||||
private fun processBuildFile(context: KobaltContext, buildFile: BuildFile): Pair<ParsedBuildFile, List<URL>> {
|
||||
val result = arrayListOf<URL>()
|
||||
|
||||
private fun parseBuildFile(context: KobaltContext, buildFile: BuildFile) : ParsedBuildFile {
|
||||
// Parse the build file so we can generate preBuildScript and buildScript from it.
|
||||
val parsedBuildFile = ParsedBuildFile(buildFile.path.toFile(), context)
|
||||
|
||||
//
|
||||
// Compile and run preBuildScriptCode, which contains all the plugins() calls extracted. This
|
||||
// will add all the dynamic plugins found in this code to Plugins.dynamicPlugins
|
||||
//
|
||||
val pluginSourceFile = KFiles.createTempFile(".kt")
|
||||
pluginSourceFile.writeText(parsedBuildFile.preBuildScriptCode, Charset.defaultCharset())
|
||||
log(2, "Saved ${pluginSourceFile.absolutePath}")
|
||||
|
||||
//
|
||||
// Compile to preBuildScript.jar
|
||||
//
|
||||
val buildScriptJar = KFiles.findBuildScriptLocation(buildFile, "preBuildScript.jar")
|
||||
val buildScriptJarFile = File(buildScriptJar)
|
||||
if (! isUpToDate(buildFile, File(buildScriptJar))) {
|
||||
buildScriptJarFile.parentFile.mkdirs()
|
||||
generateJarFile(context, BuildFile(Paths.get(pluginSourceFile.path), "Plugins"), buildScriptJarFile)
|
||||
generateVersionFile(buildScriptJarFile.parentFile)
|
||||
}
|
||||
|
||||
//
|
||||
// Run preBuildScript.jar to initialize plugins and repos
|
||||
//
|
||||
runBuildScriptJarFile(buildScriptJarFile, arrayListOf<URL>())
|
||||
|
||||
//
|
||||
// All the plug-ins are now in Plugins.dynamicPlugins, download them if they're not already
|
||||
//
|
||||
Plugins.dynamicPlugins.forEach {
|
||||
result.add(it.jarFile.get().toURI().toURL())
|
||||
}
|
||||
|
||||
return Pair(parsedBuildFile, result)
|
||||
}
|
||||
|
||||
private val VERSION_FILE = "version.txt"
|
||||
|
||||
private fun generateVersionFile(directory: File) {
|
||||
KFiles.saveFile(File(directory, VERSION_FILE), Kobalt.version)
|
||||
}
|
||||
|
||||
private fun isSameVersionFile(directory: File) =
|
||||
with(File(directory, VERSION_FILE)) {
|
||||
! exists() || (exists() && readText() == Kobalt.version)
|
||||
}
|
||||
|
||||
private fun generateJarFile(context: KobaltContext, buildFile: BuildFile, buildScriptJarFile: File) {
|
||||
val kotlintDeps = dependencyManager.calculateDependencies(null, context)
|
||||
val deps: List<String> = kotlintDeps.map { it.jarFile.get().absolutePath }
|
||||
kotlinCompilePrivate {
|
||||
classpath(files.kobaltJar)
|
||||
classpath(deps)
|
||||
sourceFiles(buildFile.path.toFile().absolutePath)
|
||||
output = File(buildScriptJarFile.absolutePath)
|
||||
}.compile(context = context)
|
||||
}
|
||||
|
||||
class BuildScriptInfo(val projects: List<Project>)
|
||||
|
||||
/**
|
||||
* Run the given preBuildScript (or buildScript) jar file, using a classloader made of the passed URL's.
|
||||
*/
|
||||
private fun runBuildScriptJarFile(buildScriptJarFile: File, urls: List<URL>) : BuildScriptInfo {
|
||||
val projects = arrayListOf<Project>()
|
||||
var stream : InputStream? = null
|
||||
val allUrls = (urls + arrayOf(
|
||||
buildScriptJarFile.toURI().toURL()) + File(files.kobaltJar).toURI().toURL())
|
||||
.toTypedArray()
|
||||
val classLoader = URLClassLoader(allUrls)
|
||||
|
||||
//
|
||||
// Install all the plugins
|
||||
//
|
||||
plugins.installPlugins(Plugins.dynamicPlugins, classLoader)
|
||||
|
||||
try {
|
||||
stream = JarInputStream(FileInputStream(buildScriptJarFile))
|
||||
var entry = stream.nextJarEntry
|
||||
|
||||
val classes = hashSetOf<Class<*>>()
|
||||
while (entry != null) {
|
||||
val name = entry.name;
|
||||
if (name.endsWith(".class")) {
|
||||
val className = name.substring(0, name.length - 6).replace("/", ".")
|
||||
var cl : Class<*>? = classLoader.loadClass(className)
|
||||
if (cl != null) {
|
||||
classes.add(cl)
|
||||
} else {
|
||||
throw KobaltException("Couldn't instantiate $className")
|
||||
}
|
||||
}
|
||||
entry = stream.nextJarEntry;
|
||||
}
|
||||
|
||||
// Invoke all the "val" found on the _DefaultPackage class (the Build.kt file)
|
||||
classes.filter { cls ->
|
||||
cls.name != "_DefaultPackage"
|
||||
}.forEach { cls ->
|
||||
cls.methods.forEach { method ->
|
||||
// Invoke vals and see if they return a Project
|
||||
if (method.name.startsWith("get") && Modifier.isStatic(method.modifiers)) {
|
||||
try {
|
||||
val r = method.invoke(null)
|
||||
if (r is Project) {
|
||||
log(2, "Found project $r in class $cls")
|
||||
projects.add(r)
|
||||
}
|
||||
} catch(ex: Throwable) {
|
||||
throw ex.cause ?: KobaltException(ex)
|
||||
}
|
||||
} else {
|
||||
val taskAnnotation = method.getAnnotation(Task::class.java)
|
||||
if (taskAnnotation != null) {
|
||||
Plugins.defaultPlugin.methodTasks.add(IPlugin.MethodTask(method, taskAnnotation))
|
||||
}
|
||||
|
||||
}}
|
||||
}
|
||||
} finally {
|
||||
stream?.close()
|
||||
}
|
||||
|
||||
validateProjects(projects)
|
||||
|
||||
//
|
||||
// Now that the build file has run, fetch all the project contributors, grab the projects from them and sort
|
||||
// them topologically
|
||||
//
|
||||
Topological<Project>().let { topologicalProjects ->
|
||||
val all = hashSetOf<Project>()
|
||||
pluginInfo.projectContributors.forEach { contributor ->
|
||||
val descriptions = contributor.projects()
|
||||
descriptions.forEach { pd ->
|
||||
all.add(pd.project)
|
||||
pd.dependsOn.forEach { dependsOn ->
|
||||
topologicalProjects.addEdge(pd.project, dependsOn)
|
||||
all.add(dependsOn)
|
||||
}
|
||||
}
|
||||
}
|
||||
val result = BuildScriptInfo(topologicalProjects.sort(ArrayList(all)))
|
||||
|
||||
with(ParsedBuildFile(buildFile, context, buildScriptUtil, dependencyManager, files)) {
|
||||
// Notify possible listeners (e.g. KobaltServer) we now have all the projects
|
||||
observable.onNext(result)
|
||||
return result
|
||||
observable.onNext(projects)
|
||||
return this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
package com.beust.kobalt.kotlin.internal
|
||||
|
||||
import com.beust.kobalt.KobaltException
|
||||
import com.beust.kobalt.Plugins
|
||||
import com.beust.kobalt.api.IPlugin
|
||||
import com.beust.kobalt.api.KobaltContext
|
||||
import com.beust.kobalt.api.Project
|
||||
import com.beust.kobalt.api.annotation.Task
|
||||
import com.beust.kobalt.kotlin.BuildFile
|
||||
import com.beust.kobalt.misc.KFiles
|
||||
import com.beust.kobalt.misc.Topological
|
||||
import com.beust.kobalt.misc.log
|
||||
import com.google.inject.Inject
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.InputStream
|
||||
import java.lang.reflect.Modifier
|
||||
import java.net.URL
|
||||
import java.net.URLClassLoader
|
||||
import java.util.*
|
||||
import java.util.jar.JarInputStream
|
||||
|
||||
class BuildScriptUtil @Inject constructor(val plugins: Plugins, val files: KFiles){
|
||||
val projects = arrayListOf<Project>()
|
||||
|
||||
/**
|
||||
* Run the given preBuildScript (or buildScript) jar file, using a classloader made of the passed URL's.
|
||||
* This list is empty when we run preBuildScript.jar but for buildScript.jar, it contains the list of
|
||||
* URL's found from running preBuildScript.jar.
|
||||
*/
|
||||
fun runBuildScriptJarFile(buildScriptJarFile: File, urls: List<URL>,
|
||||
context: KobaltContext) : List<Project> {
|
||||
var stream : InputStream? = null
|
||||
val allUrls = (urls + arrayOf(
|
||||
buildScriptJarFile.toURI().toURL()) + File(files.kobaltJar).toURI().toURL())
|
||||
.toTypedArray()
|
||||
val classLoader = URLClassLoader(allUrls)
|
||||
|
||||
//
|
||||
// Install all the plugins
|
||||
//
|
||||
plugins.installPlugins(Plugins.dynamicPlugins, classLoader)
|
||||
|
||||
//
|
||||
// Classload all the jar files and invoke their methods
|
||||
//
|
||||
try {
|
||||
stream = JarInputStream(FileInputStream(buildScriptJarFile))
|
||||
var entry = stream.nextJarEntry
|
||||
|
||||
val classes = hashSetOf<Class<*>>()
|
||||
while (entry != null) {
|
||||
val name = entry.name;
|
||||
if (name.endsWith(".class")) {
|
||||
val className = name.substring(0, name.length - 6).replace("/", ".")
|
||||
var cl : Class<*>? = classLoader.loadClass(className)
|
||||
if (cl != null) {
|
||||
classes.add(cl)
|
||||
} else {
|
||||
throw KobaltException("Couldn't instantiate $className")
|
||||
}
|
||||
}
|
||||
entry = stream.nextJarEntry;
|
||||
}
|
||||
|
||||
// Invoke all the "val" found on the _DefaultPackage class (the Build.kt file)
|
||||
classes.filter { cls ->
|
||||
cls.name != "_DefaultPackage"
|
||||
}.forEach { cls ->
|
||||
cls.methods.forEach { method ->
|
||||
// Invoke vals and see if they return a Project
|
||||
if (method.name.startsWith("get") && Modifier.isStatic(method.modifiers)) {
|
||||
try {
|
||||
val r = method.invoke(null)
|
||||
if (r is Project) {
|
||||
log(2, "Found project $r in class $cls")
|
||||
projects.add(r)
|
||||
}
|
||||
} catch(ex: Throwable) {
|
||||
throw ex.cause ?: KobaltException(ex)
|
||||
}
|
||||
} else {
|
||||
val taskAnnotation = method.getAnnotation(Task::class.java)
|
||||
if (taskAnnotation != null) {
|
||||
Plugins.defaultPlugin.methodTasks.add(IPlugin.MethodTask(method, taskAnnotation))
|
||||
}
|
||||
|
||||
}}
|
||||
}
|
||||
} finally {
|
||||
stream?.close()
|
||||
}
|
||||
|
||||
validateProjects(projects)
|
||||
|
||||
//
|
||||
// Now that the build file has run, fetch all the project contributors, grab the projects from them and sort
|
||||
// them topologically
|
||||
//
|
||||
Topological<Project>().let { topologicalProjects ->
|
||||
val all = hashSetOf<Project>()
|
||||
context.pluginInfo.projectContributors.forEach { contributor ->
|
||||
val descriptions = contributor.projects()
|
||||
descriptions.forEach { pd ->
|
||||
all.add(pd.project)
|
||||
pd.dependsOn.forEach { dependsOn ->
|
||||
topologicalProjects.addEdge(pd.project, dependsOn)
|
||||
all.add(dependsOn)
|
||||
}
|
||||
}
|
||||
}
|
||||
val result = topologicalProjects.sort(ArrayList(all))
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
fun isUpToDate(buildFile: BuildFile, jarFile: File) =
|
||||
buildFile.exists() && jarFile.exists()
|
||||
&& buildFile.lastModified < jarFile.lastModified()
|
||||
|
||||
/**
|
||||
* Make sure all the projects have a unique name.
|
||||
*/
|
||||
private fun validateProjects(projects: List<Project>) {
|
||||
val seen = hashSetOf<String>()
|
||||
projects.forEach {
|
||||
if (seen.contains(it.name)) {
|
||||
throw KobaltException("Duplicate project name: $it")
|
||||
} else {
|
||||
seen.add(it.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,17 +1,30 @@
|
|||
package com.beust.kobalt.kotlin.internal
|
||||
|
||||
import com.beust.kobalt.Plugins
|
||||
import com.beust.kobalt.api.KobaltContext
|
||||
import com.beust.kobalt.api.Project
|
||||
import com.beust.kobalt.kotlin.BuildFile
|
||||
import com.beust.kobalt.maven.DependencyManager
|
||||
import com.beust.kobalt.misc.KFiles
|
||||
import com.beust.kobalt.misc.countChar
|
||||
import com.beust.kobalt.misc.log
|
||||
import com.beust.kobalt.plugin.kotlin.kotlinCompilePrivate
|
||||
import java.io.File
|
||||
import java.net.URL
|
||||
import java.nio.charset.Charset
|
||||
import java.nio.file.Paths
|
||||
import java.util.*
|
||||
|
||||
class ParsedBuildFile(val file: File, val context: KobaltContext) {
|
||||
val plugins = arrayListOf<String>()
|
||||
class ParsedBuildFile(val buildFile: BuildFile, val context: KobaltContext, val buildScriptUtil: BuildScriptUtil,
|
||||
val dependencyManager: DependencyManager, val files: KFiles) {
|
||||
val pluginList = arrayListOf<String>()
|
||||
val repos = arrayListOf<String>()
|
||||
val profileLines = arrayListOf<String>()
|
||||
val pluginUrls = arrayListOf<URL>()
|
||||
val projects = arrayListOf<Project>()
|
||||
|
||||
private val preBuildScript = arrayListOf("import com.beust.kobalt.*",
|
||||
private val preBuildScript = arrayListOf(
|
||||
"import com.beust.kobalt.*",
|
||||
"import com.beust.kobalt.api.*")
|
||||
val preBuildScriptCode : String get() = preBuildScript.joinToString("\n")
|
||||
|
||||
|
@ -20,15 +33,16 @@ class ParsedBuildFile(val file: File, val context: KobaltContext) {
|
|||
|
||||
init {
|
||||
parseBuildFile()
|
||||
initPluginUrls()
|
||||
}
|
||||
|
||||
private fun parseBuildFile() {
|
||||
var parenCount = 0
|
||||
file.forEachLine(Charset.defaultCharset()) { line ->
|
||||
buildFile.path.toFile().forEachLine(Charset.defaultCharset()) { line ->
|
||||
var current: ArrayList<String>? = null
|
||||
var index = line.indexOf("plugins(")
|
||||
if (index >= 0) {
|
||||
current = plugins
|
||||
current = pluginList
|
||||
} else {
|
||||
index = line.indexOf("repos(")
|
||||
if (index >= 0) {
|
||||
|
@ -66,7 +80,51 @@ class ParsedBuildFile(val file: File, val context: KobaltContext) {
|
|||
}
|
||||
|
||||
repos.forEach { preBuildScript.add(it) }
|
||||
plugins.forEach { preBuildScript.add(it) }
|
||||
pluginList.forEach { preBuildScript.add(it) }
|
||||
}
|
||||
|
||||
private fun initPluginUrls() {
|
||||
//
|
||||
// Compile and run preBuildScriptCode, which contains all the plugins() calls extracted. This
|
||||
// will add all the dynamic plugins found in this code to Plugins.dynamicPlugins
|
||||
//
|
||||
val pluginSourceFile = KFiles.createTempFile(".kt")
|
||||
pluginSourceFile.writeText(preBuildScriptCode, Charset.defaultCharset())
|
||||
log(2, "Saved ${pluginSourceFile.absolutePath}")
|
||||
|
||||
//
|
||||
// Compile to preBuildScript.jar
|
||||
//
|
||||
val buildScriptJar = KFiles.findBuildScriptLocation(buildFile, "preBuildScript.jar")
|
||||
val buildScriptJarFile = File(buildScriptJar)
|
||||
if (! buildScriptUtil.isUpToDate(buildFile, File(buildScriptJar))) {
|
||||
buildScriptJarFile.parentFile.mkdirs()
|
||||
generateJarFile(context, BuildFile(Paths.get(pluginSourceFile.path), "Plugins"), buildScriptJarFile)
|
||||
VersionFile.generateVersionFile(buildScriptJarFile.parentFile)
|
||||
}
|
||||
|
||||
//
|
||||
// Run preBuildScript.jar to initialize plugins and repos
|
||||
//
|
||||
projects.addAll(buildScriptUtil.runBuildScriptJarFile(buildScriptJarFile, arrayListOf<URL>(), context))
|
||||
|
||||
//
|
||||
// All the plug-ins are now in Plugins.dynamicPlugins, download them if they're not already
|
||||
//
|
||||
Plugins.dynamicPlugins.forEach {
|
||||
pluginUrls.add(it.jarFile.get().toURI().toURL())
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateJarFile(context: KobaltContext, buildFile: BuildFile, buildScriptJarFile: File) {
|
||||
val kotlintDeps = dependencyManager.calculateDependencies(null, context)
|
||||
val deps: List<String> = kotlintDeps.map { it.jarFile.get().absolutePath }
|
||||
kotlinCompilePrivate {
|
||||
classpath(files.kobaltJar)
|
||||
classpath(deps)
|
||||
sourceFiles(buildFile.path.toFile().absolutePath)
|
||||
output = File(buildScriptJarFile.absolutePath)
|
||||
}.compile(context = context)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package com.beust.kobalt.kotlin.internal
|
||||
|
||||
import com.beust.kobalt.api.Kobalt
|
||||
import com.beust.kobalt.misc.KFiles
|
||||
import java.io.File
|
||||
|
||||
class VersionFile {
|
||||
companion object {
|
||||
private val VERSION_FILE = "version.txt"
|
||||
|
||||
fun generateVersionFile(directory: File) {
|
||||
KFiles.saveFile(File(directory, VERSION_FILE), Kobalt.version)
|
||||
}
|
||||
|
||||
fun isSameVersionFile(directory: File) =
|
||||
with(File(directory, VERSION_FILE)) {
|
||||
! exists() || (exists() && readText() == Kobalt.version)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue