1
0
Fork 0
mirror of https://github.com/ethauvin/kobalt.git synced 2025-04-27 00:38:11 -07:00

Profiles.

This commit is contained in:
Cedric Beust 2015-11-26 05:23:42 -08:00
parent 833f2e2bbf
commit 57f8ec90c4
4 changed files with 120 additions and 32 deletions

View file

@ -42,6 +42,9 @@ class Args {
@Parameter(names = arrayOf("--port"), description = "Port, if --server was specified")
var port: Int = DEFAULT_SERVER_PORT
@Parameter(names = arrayOf("--profiles"), description = "Comma-separate list of profiles to run")
var profiles: String? = null
@Parameter(names = arrayOf("--resolve"), description = "Resolve the given dependency and display its tree")
var dependency: String? = null

View file

@ -2,17 +2,29 @@ package com.beust.kobalt.api
import com.beust.kobalt.Args
import com.beust.kobalt.Plugins
import com.beust.kobalt.internal.PluginInfo
import com.beust.kobalt.Variant
import com.beust.kobalt.internal.PluginInfo
import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.misc.KobaltExecutors
public class KobaltContext(val args: Args) {
var variant: Variant = Variant()
val profiles = arrayListOf<String>()
init {
args.profiles?.split(",")?.filterNotNull()?.forEach {
profiles.add(it)
}
}
fun findPlugin(name: String) = Plugins.findPlugin(name)
//
// Injected
//
lateinit var pluginInfo: PluginInfo
lateinit var pluginProperties: PluginProperties
lateinit var dependencyManager: DependencyManager
lateinit var executors: KobaltExecutors
var variant: Variant = Variant()
}

View file

@ -6,8 +6,12 @@ import com.beust.kobalt.Plugins
import com.beust.kobalt.api.*
import com.beust.kobalt.api.annotation.Task
import com.beust.kobalt.internal.PluginInfo
import com.beust.kobalt.kotlin.internal.ParsedBuildFile
import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.misc.*
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
@ -75,7 +79,8 @@ public class BuildFileCompiler @Inject constructor(@Assisted("buildFiles") val b
private fun findProjects(context: KobaltContext): List<Project> {
val result = arrayListOf<Project>()
buildFiles.forEach { buildFile ->
val pluginUrls = findPlugInUrls(context, buildFile)
val pair = processBuildFile(context, buildFile)
val pluginUrls = pair.second
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
@ -87,8 +92,13 @@ public class BuildFileCompiler @Inject constructor(@Assisted("buildFiles") val b
}
}
maybeCompileBuildFile(context, buildFile, buildScriptJarFile, pluginUrls)
val buildScriptInfo = parseBuildScriptJarFile(buildScriptJarFile, pluginUrls)
// Write the modified Build.kt (e.g. maybe profiles were applied) to a temporary file,
// compile it and run it
val modifiedBuildFile = KFiles.createTempFile(".kt")
KFiles.saveFile(modifiedBuildFile, pair.first.buildScriptCode)
maybeCompileBuildFile(context, BuildFile(Paths.get(modifiedBuildFile.path), "Modified Build.kt"),
buildScriptJarFile, pluginUrls)
val buildScriptInfo = runBuildScriptJarFile(buildScriptJarFile, pluginUrls)
result.addAll(buildScriptInfo.projects)
}
return result
@ -123,36 +133,21 @@ public class BuildFileCompiler @Inject constructor(@Assisted("buildFiles") val b
/**
* Generate the script file with only the plugins()/repos() directives and run it. Then return
* the URL's of all the plug-ins that were found.
* - 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 findPlugInUrls(context: KobaltContext, buildFile: BuildFile): List<URL> {
private fun processBuildFile(context: KobaltContext, buildFile: BuildFile): Pair<ParsedBuildFile, List<URL>> {
val result = arrayListOf<URL>()
val pluginCode = arrayListOf(
"import com.beust.kobalt.*",
"import com.beust.kobalt.api.*"
)
var parenCount = 0
buildFile.path.toFile().forEachLine(Charset.defaultCharset()) { line ->
var index = line.indexOf("plugins(")
if (index == -1) index = line.indexOf("repos(")
if (parenCount > 0 || index >= 0) {
if (index == -1) index = 0
with(line.substring(index)) {
parenCount += line countChar '('
if (parenCount > 0) {
pluginCode.add(line)
}
parenCount -= line countChar ')'
}
}
}
// Parse the build file so we can generate preBuildScript and buildScript from it.
val parsedBuildFile = ParsedBuildFile(buildFile.path.toFile(), context)
//
// Compile and run pluginCode, which contains all the plugins() calls extracted. This
// 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(pluginCode.joinToString("\n"), Charset.defaultCharset())
pluginSourceFile.writeText(parsedBuildFile.preBuildScriptCode, Charset.defaultCharset())
log(2, "Saved ${pluginSourceFile.absolutePath}")
//
@ -169,7 +164,7 @@ public class BuildFileCompiler @Inject constructor(@Assisted("buildFiles") val b
//
// Run preBuildScript.jar to initialize plugins and repos
//
parseBuildScriptJarFile(buildScriptJarFile, arrayListOf<URL>())
runBuildScriptJarFile(buildScriptJarFile, arrayListOf<URL>())
//
// All the plug-ins are now in Plugins.dynamicPlugins, download them if they're not already
@ -178,7 +173,7 @@ public class BuildFileCompiler @Inject constructor(@Assisted("buildFiles") val b
result.add(it.jarFile.get().toURI().toURL())
}
return result
return Pair(parsedBuildFile, result)
}
private val VERSION_FILE = "version.txt"
@ -205,7 +200,10 @@ public class BuildFileCompiler @Inject constructor(@Assisted("buildFiles") val b
class BuildScriptInfo(val projects: List<Project>)
private fun parseBuildScriptJarFile(buildScriptJarFile: File, urls: List<URL>) : BuildScriptInfo {
/**
* 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(

View file

@ -0,0 +1,75 @@
package com.beust.kobalt.kotlin.internal
import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.misc.countChar
import java.io.File
import java.nio.charset.Charset
import java.util.*
class ParsedBuildFile(val file: File, val context: KobaltContext) {
val plugins = arrayListOf<String>()
val repos = arrayListOf<String>()
val profileLines = arrayListOf<String>()
private val preBuildScript = arrayListOf("import com.beust.kobalt.*",
"import com.beust.kobalt.api.*")
val preBuildScriptCode : String get() = preBuildScript.joinToString("\n")
private val buildScript = arrayListOf<String>()
val buildScriptCode : String get() = buildScript.joinToString("\n")
init {
parseBuildFile()
}
private fun parseBuildFile() {
var parenCount = 0
file.forEachLine(Charset.defaultCharset()) { line ->
var current: ArrayList<String>? = null
var index = line.indexOf("plugins(")
if (index >= 0) {
current = plugins
} else {
index = line.indexOf("repos(")
if (index >= 0) {
current = repos
}
}
if (parenCount > 0 || current != null) {
if (index == -1) index = 0
with(line.substring(index)) {
parenCount += line countChar '('
if (parenCount > 0) {
current!!.add(line)
}
parenCount -= line countChar ')'
}
}
/**
* If the current line matches one of the profile, turns the declaration into
* val profile = true, otherwise return the same line
*/
fun correctProfileLine(line: String) : String {
if (line.contains("experimental")) {
println("DONOTCOMMIT")
}
context.profiles.forEach {
if (line.matches(kotlin.text.Regex("[ \\t]*val[ \\t]+$it[ \\t]+=.*"))) {
with("val $it = true") {
profileLines.add(this)
return this
}
}
}
return line
}
buildScript.add(correctProfileLine(line))
}
repos.forEach { preBuildScript.add(it) }
plugins.forEach { preBuildScript.add(it) }
}
}