mirror of
https://github.com/ethauvin/kobalt.git
synced 2025-04-26 08:27:12 -07:00
Merge branch 'master' of github.com:cbeust/kobalt
Conflicts: src/main/kotlin/com/beust/kobalt/Main.kt
This commit is contained in:
commit
dffcee0cd4
33 changed files with 470 additions and 404 deletions
1
TODO.md
1
TODO.md
|
@ -32,6 +32,7 @@ To do:
|
|||
|
||||
Done:
|
||||
|
||||
- [x] Get rid of the $JAVA_HOME requirement
|
||||
- [x] getDependencies() should return the transitive dependencies
|
||||
- [x] Project ordering: kotlinProject(wrapper) {}
|
||||
- [x] Make files appear in download list automatically on bintray (undocumented API)
|
||||
|
|
27
kobalt.iml
27
kobalt.iml
|
@ -16,30 +16,7 @@
|
|||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib:1.0.0-beta-1038" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-compiler-embeddable:1.0.0-beta-1038" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.beust:jcommander:1.48" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.squareup.okhttp:okhttp:2.4.0" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.jsoup:jsoup:1.8.2" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.google.inject:guice:4.0" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.google.inject.extensions:guice-assistedinject:4.0" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.google.guava:guava:18.0" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.apache.maven:maven-model:3.3.3" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.github.spullara.mustache.java:compiler:0.8.18" level="project" />
|
||||
<orderEntry type="library" name="Gradle: io.reactivex:rxjava:1.0.14" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.google.code.gson:gson:2.4" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-runtime:1.0.0-beta-1038" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.squareup.okio:okio:1.4.0" level="project" />
|
||||
<orderEntry type="library" name="Gradle: javax.inject:javax.inject:1" level="project" />
|
||||
<orderEntry type="library" name="Gradle: aopalliance:aopalliance:1.0" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.codehaus.plexus:plexus-utils:3.0.20" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Gradle: org.testng:testng:6.9.6" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Gradle: com.google.inject:guice:4.0:no_aop" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Gradle: org.beanshell:bsh:2.0b4" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Gradle: org.apache.ant:ant:1.7.0" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Gradle: org.yaml:snakeyaml:1.15" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Gradle: junit:junit:4.10" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Gradle: org.apache.ant:ant-launcher:1.7.0" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-core:1.1" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="kobalt (Test)" level="project" />
|
||||
<orderEntry type="library" name="kobalt (Compile)" level="project" />
|
||||
</component>
|
||||
</module>
|
|
@ -1 +1 @@
|
|||
kobalt.version=0.217
|
||||
kobalt.version=0.219
|
|
@ -7,5 +7,7 @@
|
|||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" scope="TEST" name="kobalt (Test)" level="project" />
|
||||
<orderEntry type="library" name="kobalt (Compile)" level="project" />
|
||||
</component>
|
||||
</module>
|
|
@ -95,10 +95,13 @@ public open class Jvm constructor(
|
|||
// }
|
||||
|
||||
override public fun findExecutable(command: String): File {
|
||||
val exec = File(javaHome, "bin/" + command)
|
||||
val executable = java.io.File(os.getExecutableName(exec.getAbsolutePath()))
|
||||
if (executable.isFile()) {
|
||||
return executable
|
||||
if (javaHome != null) {
|
||||
val jdkHome = if (javaHome!!.endsWith("jre")) javaHome!!.parentFile else javaHome
|
||||
val exec = File(jdkHome, "bin/" + command)
|
||||
var executable = File(os.getExecutableName(exec.absolutePath))
|
||||
if (executable.isFile) {
|
||||
return executable
|
||||
}
|
||||
}
|
||||
|
||||
// if (userSupplied) {
|
||||
|
@ -108,12 +111,12 @@ public open class Jvm constructor(
|
|||
|
||||
val pathExecutable = os.findInPath(command)
|
||||
if (pathExecutable != null) {
|
||||
log(1, "Unable to find the ${command} executable using home: " +
|
||||
"%{javaHome}. We found it on the PATH: ${pathExecutable}.")
|
||||
log(1, "Unable to find the $command executable using home: " +
|
||||
"%{javaHome}. We found it on the PATH: $pathExecutable.")
|
||||
return pathExecutable
|
||||
}
|
||||
|
||||
warn("Unable to find the ${command} executable. Tried the java home: ${javaHome}" +
|
||||
warn("Unable to find the $command executable. Tried the java home: $javaHome" +
|
||||
" and the PATH. We will assume the executable can be ran in the current " +
|
||||
"working folder.")
|
||||
return java.io.File(os.getExecutableName(command))
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package com.beust.kobalt
|
||||
|
||||
import com.beust.jcommander.JCommander
|
||||
import com.beust.kobalt.api.*
|
||||
import com.beust.kobalt.api.Kobalt
|
||||
import com.beust.kobalt.api.PluginInfo
|
||||
import com.beust.kobalt.api.Project
|
||||
import com.beust.kobalt.internal.TaskManager
|
||||
import com.beust.kobalt.internal.remote.KobaltClient
|
||||
import com.beust.kobalt.internal.remote.KobaltServer
|
||||
|
@ -18,7 +20,6 @@ import java.io.File
|
|||
import java.nio.file.Paths
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import javax.xml.bind.JAXBContext
|
||||
|
||||
public fun main(argv: Array<String>) {
|
||||
val result = mainNoExit(argv)
|
||||
|
@ -35,6 +36,7 @@ private fun parseArgs(argv: Array<String>): Main.RunInfo {
|
|||
return Main.RunInfo(result, args)
|
||||
}
|
||||
|
||||
|
||||
public fun mainNoExit(argv: Array<String>) : Int {
|
||||
val (jc, args) = parseArgs(argv)
|
||||
Kobalt.INJECTOR = Guice.createInjector(MainModule(args))
|
||||
|
@ -55,7 +57,8 @@ private class Main @Inject constructor(
|
|||
val updateKobalt: UpdateKobalt,
|
||||
val client: KobaltClient,
|
||||
val server: KobaltServer,
|
||||
val pluginInfoDescription: PluginInfoDescription) {
|
||||
val pluginInfo: PluginInfo,
|
||||
val projectGenerator: ProjectGenerator) {
|
||||
|
||||
data class RunInfo(val jc: JCommander, val args: Args)
|
||||
|
||||
|
@ -97,11 +100,11 @@ private class Main @Inject constructor(
|
|||
|
||||
public fun runTest() {
|
||||
val file = File("src\\main\\resources\\META-INF\\plugin.xml")
|
||||
val jaxbContext = JAXBContext.newInstance(KobaltPluginXml::class.java)
|
||||
|
||||
val kotlinPlugin : KobaltPluginXml = jaxbContext.createUnmarshaller().unmarshal(file) as KobaltPluginXml
|
||||
val pluginInfo = PluginInfo.create(kotlinPlugin)
|
||||
System.out.println(kotlinPlugin.name)
|
||||
// val jaxbContext = JAXBContext.newInstance(KobaltPluginXml::class.java)
|
||||
//
|
||||
// val kotlinPlugin : KobaltPluginXml = jaxbContext.createUnmarshaller().unmarshal(file) as KobaltPluginXml
|
||||
// val pluginInfo = PluginInfo.create(kotlinPlugin)
|
||||
// System.out.println(kotlinPlugin.name)
|
||||
}
|
||||
|
||||
private fun runWithArgs(jc: JCommander, args: Args) : Int {
|
||||
|
@ -119,7 +122,7 @@ private class Main @Inject constructor(
|
|||
// --init: create a new build project and install the wrapper
|
||||
//
|
||||
Wrapper().install()
|
||||
ProjectGenerator().run(args)
|
||||
projectGenerator.run(args)
|
||||
} else if (args.usage) {
|
||||
jc.usage()
|
||||
} else if (args.serverMode) {
|
||||
|
@ -128,8 +131,7 @@ private class Main @Inject constructor(
|
|||
if (! buildFile.exists()) {
|
||||
error(buildFile.path.toFile().path + " does not exist")
|
||||
} else {
|
||||
var allProjects = listOf<Project>()
|
||||
val pluginInfo = PluginInfo(pluginInfoDescription)
|
||||
var allProjects = arrayListOf<Project>()
|
||||
try {
|
||||
allProjects = buildFileCompilerFactory.create(listOf(buildFile), pluginInfo).compileBuildFiles(args)
|
||||
} catch(ex: KobaltException) {
|
||||
|
@ -142,8 +144,8 @@ private class Main @Inject constructor(
|
|||
return 1
|
||||
} else {
|
||||
log(1, "Deleted .kobalt")
|
||||
allProjects = buildFileCompilerFactory.create(listOf(buildFile), pluginInfo)
|
||||
.compileBuildFiles(args)
|
||||
allProjects.addAll(buildFileCompilerFactory.create(listOf(buildFile), pluginInfo)
|
||||
.compileBuildFiles(args))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,7 +180,6 @@ private class Main @Inject constructor(
|
|||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun findBuildFile(): File {
|
||||
val files = arrayListOf("Build.kt", "build.kobalt", KFiles.src("build.kobalt"),
|
||||
KFiles.src("Build.kt"))
|
||||
|
|
|
@ -37,6 +37,9 @@ public class Plugins @Inject constructor (val taskManagerProvider : Provider<Tas
|
|||
companion object {
|
||||
public val MANIFEST_PLUGIN_CLASS : String = "Kobalt-Plugin-Class"
|
||||
|
||||
/** The name of the XML file describing a plug-in */
|
||||
val PLUGIN_XML = "plugin.xml"
|
||||
|
||||
private var pluginMap = hashMapOf<String, Plugin>()
|
||||
// private var storageMap = HashMap<String, HashMap<String, Any>>()
|
||||
// fun storeValue(pluginName: String, key: String, value: Any) {
|
||||
|
|
|
@ -1,133 +1,57 @@
|
|||
package com.beust.kobalt
|
||||
|
||||
import com.beust.kobalt.api.ICompilerInfo
|
||||
import com.beust.kobalt.api.Kobalt
|
||||
import com.beust.kobalt.maven.Pom
|
||||
import com.beust.kobalt.maven.Pom.Dependency
|
||||
import com.beust.kobalt.misc.KFiles
|
||||
import com.beust.kobalt.api.IInitContributor
|
||||
import com.beust.kobalt.api.PluginInfo
|
||||
import com.beust.kobalt.misc.log
|
||||
import com.github.mustachejava.DefaultMustacheFactory
|
||||
import com.google.inject.Inject
|
||||
import java.io.File
|
||||
import java.io.InputStreamReader
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
import java.util.ArrayList
|
||||
import java.util.Collections
|
||||
import java.util.HashMap
|
||||
import java.io.FileOutputStream
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Generate a new project.
|
||||
* Invoked with --init. Generate a new project.
|
||||
*/
|
||||
public class ProjectGenerator {
|
||||
public class ProjectGenerator @Inject constructor(val pluginInfo: PluginInfo){
|
||||
companion object {
|
||||
/**
|
||||
* Turns a dot property into a proper Kotlin identifier, e.g. common.version -> commonVersion
|
||||
*/
|
||||
fun translate(key: String): String {
|
||||
return key.split('.').mapIndexed( { index, value -> if (index == 0) value else value.upperFirst() })
|
||||
fun toIdentifier(key: String): String {
|
||||
fun upperFirst(s: String) = if (s.isBlank()) s else s.substring(0, 1).toUpperCase() + s.substring(1)
|
||||
|
||||
return key.split('.').mapIndexed( { index, value -> if (index == 0) value else upperFirst(value) })
|
||||
.joinToString("")
|
||||
}
|
||||
}
|
||||
|
||||
fun run(args: Args) {
|
||||
if (File(args.buildFile).exists()) {
|
||||
log(1, "Build file ${args.buildFile} already exists, not overwriting it")
|
||||
return
|
||||
val contributor = findBestInitContributor(File("."))
|
||||
if (contributor != null) {
|
||||
contributor.generateBuildFile(FileOutputStream(File(args.buildFile)))
|
||||
log(1, "Created ${args.buildFile}")
|
||||
} else {
|
||||
log(1, "Couldn't identify project, not generating any build file")
|
||||
}
|
||||
}
|
||||
|
||||
val compilerInfos = detect(File("."))
|
||||
if (compilerInfos.size > 1) {
|
||||
log(1, "Multi language project detected, not supported yet")
|
||||
}
|
||||
val map = hashMapOf<String, Any?>()
|
||||
map.put("directive", if (compilerInfos.isEmpty()) "project" else compilerInfos.get(0).directive)
|
||||
if (compilerInfos.size > 0) {
|
||||
compilerInfos.get(0).let {
|
||||
val currentDir = File(".").absoluteFile.parentFile
|
||||
with(map) {
|
||||
put("name", currentDir.name)
|
||||
put("group", "com.example")
|
||||
put("version", "0.1")
|
||||
put("directory", currentDir.absolutePath)
|
||||
put("sourceDirectories", it.defaultSourceDirectories)
|
||||
put("sourceDirectoriesTest", it.defaultTestDirectories)
|
||||
put("imports", "import com.beust.kobalt.plugin.${it.name}.*")
|
||||
put("directive", it.name + "Project")
|
||||
/**
|
||||
* Run through all the IInitContributors and return the best one.
|
||||
*/
|
||||
private fun findBestInitContributor(dir: File) : IInitContributor? {
|
||||
val result = arrayListOf<Pair<IInitContributor, Int>>()
|
||||
pluginInfo.initContributors.forEach {
|
||||
it.filesManaged(dir).let { count ->
|
||||
if (count > 0) {
|
||||
result.add(Pair(it, count))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var mainDeps = arrayListOf<Dependency>()
|
||||
var testDeps = arrayListOf<Dependency>()
|
||||
map.put("mainDependencies", mainDeps)
|
||||
map.put("testDependencies", testDeps)
|
||||
File("pom.xml").let {
|
||||
if (it.absoluteFile.exists()) {
|
||||
importPom(it, mainDeps, testDeps, map)
|
||||
}
|
||||
}
|
||||
|
||||
val fileInputStream = javaClass.classLoader.getResource("build-template.mustache").openStream()
|
||||
val sw = StringWriter()
|
||||
val pw = PrintWriter(sw)
|
||||
var mf = DefaultMustacheFactory();
|
||||
var mustache = mf.compile(InputStreamReader(fileInputStream), "kobalt");
|
||||
mustache.execute(pw, map).flush();
|
||||
KFiles.saveFile(File(args.buildFile), sw.toString())
|
||||
}
|
||||
|
||||
private fun importPom(pomFile: File, mainDeps: ArrayList<Dependency>, testDeps: ArrayList<Dependency>,
|
||||
map: HashMap<String, Any?>) {
|
||||
var pom = Pom("imported", pomFile.absoluteFile)
|
||||
with(map) {
|
||||
put("group", pom.groupId ?: "com.example")
|
||||
put("artifactId", pom.artifactId ?: "com.example")
|
||||
put("version", pom.version ?: "0.1")
|
||||
put("name", pom.name ?: pom.artifactId)
|
||||
put("repositories", pom.repositories.map({ "\"${it}\"" }).joinToString(","))
|
||||
}
|
||||
|
||||
val properties = pom.properties
|
||||
val mapped = properties.entries.toMap({it.key}, {translate(it.key)})
|
||||
|
||||
map.put("properties", properties.entries.map({ Pair(mapped.get(it.key), it.value) }))
|
||||
|
||||
val partition = pom.dependencies.groupBy { it.scope }
|
||||
.flatMap { it.value }
|
||||
.map { updateVersion(it, mapped) }
|
||||
.sortedBy { it.groupId + ":" + it.artifactId }
|
||||
.partition { it.scope != "test" }
|
||||
|
||||
mainDeps.addAll(partition.first)
|
||||
testDeps.addAll(partition.second)
|
||||
}
|
||||
|
||||
private fun updateVersion(dep: Dependency, mapped: Map<String, String>) =
|
||||
if ( dep.version.startsWith("\${")) {
|
||||
val property = dep.version.substring(2, dep.version.length - 1)
|
||||
Dependency(dep.groupId, dep.artifactId, dep.packaging, "\${${mapped.get(property)}}", dep.optional,
|
||||
dep.scope)
|
||||
if (result.size > 0) {
|
||||
Collections.sort(result, { p1, p2 -> p2.second.compareTo(p1.second) })
|
||||
return result[0].first
|
||||
} else {
|
||||
dep
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detect all the languages contained in this project.
|
||||
*/
|
||||
private fun detect(dir: File) : List<ICompilerInfo> {
|
||||
val result = arrayListOf<Pair<ICompilerInfo, List<File>>>()
|
||||
Kobalt.compilers.forEach {
|
||||
val managedFiles = it.findManagedFiles(dir)
|
||||
if (managedFiles.size > 0) {
|
||||
result.add(Pair(it, managedFiles))
|
||||
}
|
||||
}
|
||||
Collections.sort(result, { p1, p2 -> p1.second.size.compareTo(p2.second.size) })
|
||||
return result.map { it.first }
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.upperFirst(): String {
|
||||
return if (this.isBlank()) this else this.substring(0, 1).toUpperCase() + this.substring(1)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
package com.beust.kobalt
|
||||
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
import javax.inject.Inject
|
||||
|
||||
public class SystemProperties {
|
||||
companion object {
|
||||
val javaBase = System.getenv("JAVA_HOME") ?: throw IllegalArgumentException("JAVA_HOME not defined")
|
||||
val javaBase = System.getProperty("java.home") ?:
|
||||
(System.getenv("JAVA_HOME") ?: throw IllegalArgumentException("JAVA_HOME not defined"))
|
||||
val javaVersion = System.getProperty("java.version")
|
||||
val homeDir = System.getProperty("user.home")
|
||||
val tmpDir = System.getProperty("java.io.tmpdir")
|
||||
|
|
|
@ -2,38 +2,17 @@ package com.beust.kobalt.api
|
|||
|
||||
import com.beust.kobalt.Plugins
|
||||
import com.google.inject.Injector
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.util.*
|
||||
|
||||
public interface ICompilerInfo {
|
||||
/** Used to detect what kind of language this project is */
|
||||
fun findManagedFiles(dir: File) : List<File>
|
||||
|
||||
/** Used to generate the imports */
|
||||
val name: String
|
||||
|
||||
/** Used to generate the imports */
|
||||
val directive: String
|
||||
|
||||
val defaultSourceDirectories : ArrayList<String>
|
||||
val defaultTestDirectories : ArrayList<String>
|
||||
}
|
||||
|
||||
public class Kobalt {
|
||||
companion object {
|
||||
lateinit var INJECTOR : Injector
|
||||
|
||||
public val compilers : ArrayList<ICompilerInfo> = arrayListOf()
|
||||
|
||||
var context: KobaltContext? = null
|
||||
|
||||
fun registerCompiler(c: ICompilerInfo) {
|
||||
compilers.add(c)
|
||||
}
|
||||
|
||||
private val DEFAULT_REPOS = arrayListOf(
|
||||
"http://repo1.maven.org/maven2/",
|
||||
"https://repository.jboss.org/nexus/content/repositories/root_repository/",
|
||||
|
|
|
@ -1,104 +0,0 @@
|
|||
package com.beust.kobalt.api
|
||||
|
||||
import com.beust.kobalt.maven.IClasspathDependency
|
||||
import com.beust.kobalt.plugin.java.JavaPlugin
|
||||
import com.beust.kobalt.plugin.kotlin.KotlinPlugin
|
||||
import java.util.*
|
||||
import javax.xml.bind.annotation.XmlElement
|
||||
import javax.xml.bind.annotation.XmlRootElement
|
||||
|
||||
class ProjectDescription(val project: Project, val dependsOn: List<Project>)
|
||||
|
||||
interface IProjectContributor {
|
||||
fun projects() : List<ProjectDescription>
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement this interface in order to add your own entries to the classpath. A list of contributors
|
||||
* can be found on the `KobaltContext`.
|
||||
*/
|
||||
interface IClasspathContributor {
|
||||
fun entriesFor(project: Project) : Collection<IClasspathDependency>
|
||||
}
|
||||
|
||||
interface IFactory {
|
||||
fun <T> instanceOf(c: Class<T>) : T
|
||||
}
|
||||
|
||||
class ContributorFactory : IFactory {
|
||||
override fun <T> instanceOf(c: Class<T>) : T = Kobalt.INJECTOR.getInstance(c)
|
||||
}
|
||||
|
||||
/**
|
||||
* All the information gathered from the various plugin.xml that were collected.
|
||||
*/
|
||||
class PluginInfoDescription {
|
||||
fun <T> instanceOf(c: Class<T>) : T = Kobalt.INJECTOR.getInstance(c)
|
||||
|
||||
val projectContributors : ArrayList<Class<out IProjectContributor>> =
|
||||
arrayListOf(JavaPlugin::class.java, KotlinPlugin::class.java)
|
||||
|
||||
val classpathContributors: ArrayList<Class<out IClasspathContributor>> =
|
||||
arrayListOf(KotlinPlugin::class.java)
|
||||
|
||||
// Future contributors:
|
||||
// compilerArgs
|
||||
// source files
|
||||
// compilers
|
||||
// --init
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn the classes found in PluginInfoDescription into concrete objects that plugins can then use.
|
||||
*/
|
||||
class PluginInfo(val description: PluginInfoDescription?) {
|
||||
val projectContributors = arrayListOf<IProjectContributor>()
|
||||
val classpathContributors = arrayListOf<IClasspathContributor>()
|
||||
|
||||
companion object {
|
||||
fun create(xml: KobaltPluginXml) : PluginInfo {
|
||||
val factory = Class.forName(xml.factoryClassName).newInstance() as IFactory
|
||||
val result = PluginInfo(null)
|
||||
xml.classpathContributors?.className?.forEach {
|
||||
result.classpathContributors.add(factory.instanceOf(Class.forName(it)) as IClasspathContributor)
|
||||
}
|
||||
xml.projectContributors?.className?.forEach {
|
||||
result.projectContributors.add(factory.instanceOf(Class.forName(it)) as IProjectContributor)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
if (description != null) {
|
||||
classpathContributors.addAll(description.classpathContributors.map { description.instanceOf(it) })
|
||||
projectContributors.addAll(description.projectContributors.map { description.instanceOf(it) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ContributorXml {
|
||||
@XmlElement @JvmField
|
||||
val name: String? = null
|
||||
}
|
||||
|
||||
class ContributorsXml {
|
||||
@XmlElement(name = "class-name") @JvmField
|
||||
var className: List<String> = arrayListOf<String>()
|
||||
}
|
||||
|
||||
@XmlRootElement(name = "kobalt-plugin")
|
||||
class KobaltPluginXml {
|
||||
@XmlElement @JvmField
|
||||
var name: String? = null
|
||||
|
||||
@XmlElement(name = "factory-class-name") @JvmField
|
||||
var factoryClassName: String? = null
|
||||
|
||||
@XmlElement(name = "classpath-contributors") @JvmField
|
||||
var classpathContributors : ContributorsXml? = null
|
||||
|
||||
@XmlElement(name = "project-contributors") @JvmField
|
||||
var projectContributors : ContributorsXml? = null
|
||||
}
|
||||
|
155
src/main/kotlin/com/beust/kobalt/api/KobaltPluginXml.kt
Normal file
155
src/main/kotlin/com/beust/kobalt/api/KobaltPluginXml.kt
Normal file
|
@ -0,0 +1,155 @@
|
|||
package com.beust.kobalt.api
|
||||
|
||||
import com.beust.kobalt.maven.IClasspathDependency
|
||||
import com.beust.kobalt.misc.KFiles
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import javax.xml.bind.JAXBContext
|
||||
import javax.xml.bind.annotation.XmlElement
|
||||
import javax.xml.bind.annotation.XmlRootElement
|
||||
|
||||
//
|
||||
// Operations related to the parsing of plugin.xml: contributors, XML mapping, etc...
|
||||
//
|
||||
|
||||
/////
|
||||
// Contributors
|
||||
//
|
||||
|
||||
/**
|
||||
* Plugins that create project need to implement this interface.
|
||||
*/
|
||||
interface IProjectContributor {
|
||||
fun projects() : List<ProjectDescription>
|
||||
}
|
||||
|
||||
class ProjectDescription(val project: Project, val dependsOn: List<Project>)
|
||||
|
||||
/**
|
||||
* Plugins that export classpath entries need to implement this interface.
|
||||
*/
|
||||
interface IClasspathContributor {
|
||||
fun entriesFor(project: Project) : Collection<IClasspathDependency>
|
||||
}
|
||||
|
||||
/**
|
||||
* The factory function to use to instantiate all the contributors and other entities
|
||||
* found in plugin.xml.
|
||||
*/
|
||||
interface IFactory {
|
||||
fun <T> instanceOf(c: Class<T>) : T
|
||||
}
|
||||
|
||||
class ContributorFactory : IFactory {
|
||||
override fun <T> instanceOf(c: Class<T>) : T = Kobalt.INJECTOR.getInstance(c)
|
||||
}
|
||||
|
||||
/**
|
||||
* Plugins that want to participate in the --init process (they can generate files to initialize
|
||||
* a new project).
|
||||
*/
|
||||
interface IInitContributor {
|
||||
/**
|
||||
* How many files your plug-in understands in the given directory. The contributor with the
|
||||
* highest number will be asked to generate the build file.
|
||||
*/
|
||||
fun filesManaged(dir: File): Int
|
||||
|
||||
/**
|
||||
* Generate the Build.kt file into the given OutputStream.
|
||||
*/
|
||||
fun generateBuildFile(os: OutputStream)
|
||||
}
|
||||
|
||||
/////
|
||||
// XML parsing
|
||||
//
|
||||
// The following classes are used by JAXB to parse the plugin.xml file.
|
||||
|
||||
/**
|
||||
* The root element of plugin.xml
|
||||
*/
|
||||
@XmlRootElement(name = "kobalt-plugin")
|
||||
class KobaltPluginXml {
|
||||
@XmlElement @JvmField
|
||||
var name: String? = null
|
||||
|
||||
@XmlElement(name = "factory-class-name") @JvmField
|
||||
var factoryClassName: String? = null
|
||||
|
||||
@XmlElement(name = "classpath-contributors") @JvmField
|
||||
var classpathContributors : ContributorsXml? = null
|
||||
|
||||
@XmlElement(name = "project-contributors") @JvmField
|
||||
var projectContributors : ContributorsXml? = null
|
||||
|
||||
@XmlElement(name = "init-contributors") @JvmField
|
||||
var initContributors : ContributorsXml? = null
|
||||
}
|
||||
|
||||
class ContributorXml {
|
||||
@XmlElement @JvmField
|
||||
val name: String? = null
|
||||
}
|
||||
|
||||
class ContributorsXml {
|
||||
@XmlElement(name = "class-name") @JvmField
|
||||
var className: List<String> = arrayListOf()
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn a KobaltPluginXml (the raw content of plugin.xml mapped to POJO's) into a PluginInfo object, which contains
|
||||
* all the contributors instantiated and other information that Kobalt can actually use. Kobalt code that
|
||||
* needs to access plug-in info can then just inject a PluginInfo object.
|
||||
*/
|
||||
class PluginInfo(val xml: KobaltPluginXml) {
|
||||
val projectContributors = arrayListOf<IProjectContributor>()
|
||||
val classpathContributors = arrayListOf<IClasspathContributor>()
|
||||
val initContributors = arrayListOf<IInitContributor>()
|
||||
|
||||
// Future contributors:
|
||||
// compilerArgs
|
||||
// source files
|
||||
// compilers
|
||||
// repos
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Read Kobalt's own plugin.xml.
|
||||
*/
|
||||
fun readKobaltPluginXml() : PluginInfo {
|
||||
val pluginXml = KFiles.joinDir("META-INF", "plugin.xml") // Plugins.PLUGIN_XML)
|
||||
val url = Kobalt::class.java.classLoader.getResource(pluginXml)
|
||||
if (url != null) {
|
||||
return readPluginXml(url.openConnection().inputStream)
|
||||
} else {
|
||||
throw AssertionError("Couldn't find $pluginXml")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a general plugin.xml.
|
||||
*/
|
||||
private fun readPluginXml(ins: InputStream): PluginInfo {
|
||||
val jaxbContext = JAXBContext.newInstance(KobaltPluginXml::class.java)
|
||||
val kotlinPlugin: KobaltPluginXml = jaxbContext.createUnmarshaller().unmarshal(ins)
|
||||
as KobaltPluginXml
|
||||
return PluginInfo(kotlinPlugin)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
val factory = Class.forName(xml.factoryClassName).newInstance() as IFactory
|
||||
xml.classpathContributors?.className?.forEach {
|
||||
classpathContributors.add(factory.instanceOf(Class.forName(it)) as IClasspathContributor)
|
||||
}
|
||||
xml.projectContributors?.className?.forEach {
|
||||
projectContributors.add(factory.instanceOf(Class.forName(it)) as IProjectContributor)
|
||||
}
|
||||
xml.initContributors?.className?.forEach {
|
||||
initContributors.add(factory.instanceOf(Class.forName(it)) as IInitContributor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.beust.kobalt.api
|
||||
|
||||
import com.beust.kobalt.api.annotation.Directive
|
||||
import com.beust.kobalt.internal.IProjectInfo
|
||||
import com.beust.kobalt.maven.IClasspathDependency
|
||||
import com.beust.kobalt.maven.MavenDependency
|
||||
import com.beust.kobalt.misc.KFiles
|
||||
|
@ -16,11 +17,11 @@ open public class Project(
|
|||
@Directive open var packaging: String? = null,
|
||||
@Directive open var dependencies: Dependencies? = null,
|
||||
@Directive open var sourceSuffix : String = "",
|
||||
@Directive open var compilerInfo : ICompilerInfo,
|
||||
@Directive open var description : String = "",
|
||||
@Directive open var scm : Scm? = null,
|
||||
@Directive open var url: String? = null,
|
||||
@Directive open var licenses: List<License> = arrayListOf<License>()) {
|
||||
@Directive open var licenses: List<License> = arrayListOf<License>(),
|
||||
val projectInfo: IProjectInfo) {
|
||||
|
||||
var testArgs: ArrayList<String> = arrayListOf()
|
||||
|
||||
|
@ -44,7 +45,7 @@ open public class Project(
|
|||
}
|
||||
|
||||
var sourceDirectories : ArrayList<String> = arrayListOf()
|
||||
get() = if (field.isEmpty()) compilerInfo.defaultSourceDirectories else field
|
||||
get() = if (field.isEmpty()) projectInfo.defaultSourceDirectories else field
|
||||
set(value) {
|
||||
field = value
|
||||
}
|
||||
|
@ -57,7 +58,7 @@ open public class Project(
|
|||
}
|
||||
|
||||
var sourceDirectoriesTest : ArrayList<String> = arrayListOf()
|
||||
get() = if (field.isEmpty()) compilerInfo.defaultTestDirectories
|
||||
get() = if (field.isEmpty()) projectInfo.defaultTestDirectories
|
||||
else field
|
||||
set(value) {
|
||||
field = value
|
||||
|
|
99
src/main/kotlin/com/beust/kobalt/internal/BuildGenerator.kt
Normal file
99
src/main/kotlin/com/beust/kobalt/internal/BuildGenerator.kt
Normal file
|
@ -0,0 +1,99 @@
|
|||
package com.beust.kobalt.internal
|
||||
|
||||
import com.beust.kobalt.ProjectGenerator
|
||||
import com.beust.kobalt.api.IInitContributor
|
||||
import com.beust.kobalt.maven.Pom
|
||||
import com.beust.kobalt.misc.KFiles
|
||||
import com.github.mustachejava.DefaultMustacheFactory
|
||||
import java.io.*
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Abstract base class for the build generators that use build-template.mustache.
|
||||
*/
|
||||
abstract class BuildGenerator : IInitContributor {
|
||||
abstract val defaultSourceDirectories : ArrayList<String>
|
||||
abstract val defaultTestDirectories : ArrayList<String>
|
||||
abstract val directive : String
|
||||
abstract val name : String
|
||||
abstract val fileMatch : (String) -> Boolean
|
||||
|
||||
override fun generateBuildFile(os: OutputStream) {
|
||||
PrintWriter(os).use {
|
||||
it.print(buildFileContent)
|
||||
}
|
||||
}
|
||||
|
||||
override fun filesManaged(dir: File) = KFiles.findRecursively(dir, fileMatch).size
|
||||
|
||||
private fun importPom(pomFile: File, mainDeps: ArrayList<Pom.Dependency>, testDeps: ArrayList<Pom.Dependency>,
|
||||
map: HashMap<String, Any?>) {
|
||||
var pom = Pom("imported", pomFile.absoluteFile)
|
||||
with(map) {
|
||||
put("group", pom.groupId ?: "com.example")
|
||||
put("artifactId", pom.artifactId ?: "com.example")
|
||||
put("version", pom.version ?: "0.1")
|
||||
put("name", pom.name ?: pom.artifactId)
|
||||
put("repositories", pom.repositories.map({ "\"$it\"" }).joinToString(","))
|
||||
}
|
||||
|
||||
val properties = pom.properties
|
||||
val mapped = properties.entries.toMap({it.key}, { ProjectGenerator.toIdentifier(it.key) })
|
||||
|
||||
map.put("properties", properties.entries.map({ Pair(mapped[it.key], it.value) }))
|
||||
|
||||
val partition = pom.dependencies.groupBy { it.scope }
|
||||
.flatMap { it.value }
|
||||
.map { updateVersion(it, mapped) }
|
||||
.sortedBy { it.groupId + ":" + it.artifactId }
|
||||
.partition { it.scope != "test" }
|
||||
|
||||
mainDeps.addAll(partition.first)
|
||||
testDeps.addAll(partition.second)
|
||||
}
|
||||
|
||||
private fun updateVersion(dep: Pom.Dependency, mapped: Map<String, String>) =
|
||||
if ( dep.version.startsWith("\${")) {
|
||||
val property = dep.version.substring(2, dep.version.length - 1)
|
||||
Pom.Dependency(dep.groupId, dep.artifactId, dep.packaging, "\${${mapped[property]}}", dep.optional,
|
||||
dep.scope)
|
||||
} else {
|
||||
dep
|
||||
}
|
||||
|
||||
private val buildFileContent: String
|
||||
get() {
|
||||
val map = hashMapOf<String, Any?>()
|
||||
map.put("directive", directive)
|
||||
val currentDir = File(".").absoluteFile.parentFile
|
||||
with(map) {
|
||||
put("name", currentDir.name)
|
||||
put("group", "com.example")
|
||||
put("version", "0.1")
|
||||
put("directory", currentDir.absolutePath)
|
||||
put("sourceDirectories", defaultSourceDirectories)
|
||||
put("sourceDirectoriesTest", defaultTestDirectories)
|
||||
put("imports", "import com.beust.kobalt.plugin.$name.*")
|
||||
put("directive", name + "Project")
|
||||
}
|
||||
|
||||
var mainDeps = arrayListOf<Pom.Dependency>()
|
||||
var testDeps = arrayListOf<Pom.Dependency>()
|
||||
map.put("mainDependencies", mainDeps)
|
||||
map.put("testDependencies", testDeps)
|
||||
File("pom.xml").let {
|
||||
if (it.absoluteFile.exists()) {
|
||||
importPom(it, mainDeps, testDeps, map)
|
||||
}
|
||||
}
|
||||
|
||||
val fileInputStream = javaClass.classLoader.getResource("build-template.mustache").openStream()
|
||||
val sw = StringWriter()
|
||||
val pw = PrintWriter(sw)
|
||||
var mf = DefaultMustacheFactory();
|
||||
var mustache = mf.compile(InputStreamReader(fileInputStream), "kobalt");
|
||||
mustache.execute(pw, map).flush();
|
||||
return sw.toString()
|
||||
}
|
||||
}
|
||||
|
11
src/main/kotlin/com/beust/kobalt/internal/ProjectInfo.kt
Normal file
11
src/main/kotlin/com/beust/kobalt/internal/ProjectInfo.kt
Normal file
|
@ -0,0 +1,11 @@
|
|||
package com.beust.kobalt.internal
|
||||
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Data that is useful for projects to have but should not be specified in the DSL.
|
||||
*/
|
||||
interface IProjectInfo {
|
||||
val defaultSourceDirectories: ArrayList<String>
|
||||
val defaultTestDirectories: ArrayList<String>
|
||||
}
|
|
@ -2,7 +2,6 @@ package com.beust.kobalt.internal.remote
|
|||
|
||||
import com.beust.kobalt.Args
|
||||
import com.beust.kobalt.api.PluginInfo
|
||||
import com.beust.kobalt.api.PluginInfoDescription
|
||||
import com.beust.kobalt.kotlin.BuildFile
|
||||
import com.beust.kobalt.kotlin.BuildFileCompiler
|
||||
import com.beust.kobalt.maven.DependencyManager
|
||||
|
@ -26,11 +25,11 @@ import javax.inject.Inject
|
|||
*/
|
||||
class GetDependenciesCommand @Inject constructor(val executors: KobaltExecutors,
|
||||
val buildFileCompilerFactory: BuildFileCompiler.IFactory, val args: Args,
|
||||
val dependencyManager: DependencyManager, val pluginInfoDescription: PluginInfoDescription) : ICommand {
|
||||
val dependencyManager: DependencyManager, val pluginInfo: PluginInfo) : ICommand {
|
||||
override val name = "getDependencies"
|
||||
override fun run(sender: ICommandSender, received: JsonObject) {
|
||||
val buildFile = BuildFile(Paths.get(received.get("buildFile").asString), "GetDependenciesCommand")
|
||||
val scriptCompiler = buildFileCompilerFactory.create(listOf(buildFile), PluginInfo(pluginInfoDescription))
|
||||
val scriptCompiler = buildFileCompilerFactory.create(listOf(buildFile), pluginInfo)
|
||||
scriptCompiler.observable.subscribe {
|
||||
buildScriptInfo -> if (buildScriptInfo.projects.size > 0) {
|
||||
sender.sendData(toData(buildScriptInfo))
|
||||
|
|
|
@ -55,7 +55,33 @@ public class KFiles {
|
|||
|
||||
public val TEST_CLASSES_DIR : String = "test-classes"
|
||||
|
||||
public fun joinDir(vararg ts: String): String = ts.toArrayList().joinToString(File.separator)
|
||||
/**
|
||||
* Join the paths elements with the file separator.
|
||||
*/
|
||||
fun joinDir(paths: List<String>): String = paths.joinToString(File.separator)
|
||||
|
||||
/**
|
||||
* Join the paths elements with the file separator.
|
||||
*/
|
||||
fun joinDir(vararg ts: String): String = ts.toArrayList().joinToString(File.separator)
|
||||
|
||||
/**
|
||||
* The paths elements are expected to be a directory. Make that directory and join the
|
||||
* elements with the file separator.
|
||||
*/
|
||||
fun joinAndMakeDir(paths: List<String>) = joinDir(paths).apply { File(this).mkdirs() }
|
||||
|
||||
/**
|
||||
* The paths elements are expected to be a directory. Make that directory and join the
|
||||
* elements with the file separator.
|
||||
*/
|
||||
fun joinAndMakeDir(vararg ts: String) = joinAndMakeDir(ts.toList())
|
||||
|
||||
/**
|
||||
* The paths elements are expected to be a file. Make that parent directory of that file and join the
|
||||
* elements with the file separator.
|
||||
*/
|
||||
fun joinFileAndMakeDir(vararg ts: String) = joinDir(joinAndMakeDir(ts.slice(0..ts.size - 2)), ts[ts.size - 1])
|
||||
|
||||
fun makeDir(dir: String, s: String? = null) =
|
||||
(if (s != null) File(dir, s) else File(dir)).apply { mkdirs() }
|
||||
|
@ -148,20 +174,6 @@ public class KFiles {
|
|||
}
|
||||
}
|
||||
|
||||
// public fun copy(from: InputStream, to: OutputStream, bufSize: Int): Long {
|
||||
// val buf = ByteArray(bufSize)
|
||||
// var total: Long = 0
|
||||
// while (true) {
|
||||
// val r = from.read(buf, 0, buf.size())
|
||||
// if (r == -1) {
|
||||
// break
|
||||
// }
|
||||
// to.write(buf, 0, r)
|
||||
// total += r.toLong()
|
||||
// }
|
||||
// return total
|
||||
// }
|
||||
|
||||
public fun createTempFile(suffix : String = "", deleteOnExit: Boolean = false) : File =
|
||||
File.createTempFile("kobalt", suffix, File(SystemProperties.tmpDir)).let {
|
||||
if (deleteOnExit) it.deleteOnExit()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.beust.kobalt.misc
|
||||
|
||||
import com.beust.kobalt.Args
|
||||
import com.beust.kobalt.api.PluginInfo
|
||||
import com.beust.kobalt.kotlin.BuildFileCompiler
|
||||
import com.beust.kobalt.maven.*
|
||||
import com.beust.kobalt.plugin.publish.JCenterApi
|
||||
|
@ -9,7 +10,6 @@ import com.google.inject.BindingAnnotation
|
|||
import com.google.inject.Provider
|
||||
import com.google.inject.TypeLiteral
|
||||
import com.google.inject.assistedinject.FactoryModuleBuilder
|
||||
import java.lang.annotation.RetentionPolicy
|
||||
import java.util.concurrent.ExecutorService
|
||||
|
||||
//@Singleton
|
||||
|
@ -49,9 +49,12 @@ public open class MainModule(val args: Args) : AbstractModule() {
|
|||
bind(object: TypeLiteral<KobaltExecutors>() {}).toInstance(executors)
|
||||
bind(object: TypeLiteral<ExecutorService>() {}).annotatedWith(DependencyExecutor::class.java)
|
||||
.toInstance(executors.dependencyExecutor)
|
||||
bind(Args::class.java).toProvider(object : Provider<Args> {
|
||||
bind(Args::class.java).toProvider(object: Provider<Args> {
|
||||
override fun get(): Args? = args
|
||||
})
|
||||
bind(PluginInfo::class.java).toProvider(object: Provider<PluginInfo> {
|
||||
override fun get(): PluginInfo? = PluginInfo.readKobaltPluginXml()
|
||||
})
|
||||
|
||||
|
||||
// bindListener(Matchers.any(), object: TypeListener {
|
||||
|
|
|
@ -6,10 +6,13 @@ import java.io.InputStream
|
|||
import java.io.InputStreamReader
|
||||
|
||||
open class RunCommand(val command: String) {
|
||||
val defaultSuccess = { output: List<String> -> log(1, "Success:\n " + output.joinToString("\n"))}
|
||||
val defaultError = { output: List<String> -> log(1, "Error:\n " + output.joinToString("\n"))}
|
||||
val defaultSuccess = { output: List<String> -> log(2, "Success:\n " + output.joinToString("\n"))}
|
||||
val defaultError = {
|
||||
output: List<String> -> error("Error:\n " + output.joinToString("\n"))
|
||||
}
|
||||
|
||||
var directory = File(".")
|
||||
var env = hashMapOf<String, String>()
|
||||
|
||||
fun run(args: List<String>, error: Function1<List<String>, Unit>? = defaultError,
|
||||
success: Function1<List<String>, Unit>? = defaultSuccess) : Int {
|
||||
|
@ -19,9 +22,13 @@ open class RunCommand(val command: String) {
|
|||
|
||||
val pb = ProcessBuilder(allArgs)
|
||||
pb.directory(directory)
|
||||
log(2, "Running command: " + allArgs.joinToString(" "))
|
||||
log(2, "Running command: " + allArgs.joinToString(" ") + "\n Current directory: $directory")
|
||||
val process = pb.start()
|
||||
pb.environment().put("ANDROID_HOME", "/Users/beust/android/adt-bundle-mac-x86_64-20140702/sdk")
|
||||
pb.environment().let { pbEnv ->
|
||||
env.forEach {
|
||||
pbEnv.put(it.key, it.value)
|
||||
}
|
||||
}
|
||||
val errorCode = process.waitFor()
|
||||
if (errorCode != 0 && error != null) {
|
||||
error(fromStream(process.errorStream))
|
||||
|
|
|
@ -62,14 +62,6 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler) :
|
|||
|
||||
override fun accept(project: Project) = configurations.containsKey(project.name!!)
|
||||
|
||||
fun dirGet(dir: Path, vararg others: String) : String {
|
||||
val result = Paths.get(dir.toString(), *others)
|
||||
with(result.toFile()) {
|
||||
mkdirs()
|
||||
}
|
||||
return result.toString()
|
||||
}
|
||||
|
||||
val flavor = "debug"
|
||||
|
||||
fun compileSdkVersion(project: Project) = configurations[project.name!!]?.compileSdkVersion
|
||||
|
@ -96,18 +88,16 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler) :
|
|||
fun androidJar(project: Project) : Path =
|
||||
Paths.get(androidHome(project), "platforms", "android-${compileSdkVersion(project)}", "android.jar")
|
||||
|
||||
fun generated(project: Project) = Paths.get(project.directory, "app", "build", "generated")
|
||||
private fun generated(project: Project) = Paths.get(project.buildDirectory, "app", "build", "generated")
|
||||
private fun intermediates(project: Project) = Paths.get(project.buildDirectory, "app", "build", "intermediates")
|
||||
|
||||
private fun aapt(project: Project) = "${androidHome(project)}/build-tools/${buildToolsVersion(project)}/aapt"
|
||||
|
||||
private fun temporaryApk(project: Project, flavor: String) = apk(project, flavor, "ap_")
|
||||
private fun temporaryApk(project: Project, flavor: String)
|
||||
= KFiles.joinFileAndMakeDir(project.buildDirectory!!, "intermediates", "res", "resources-$flavor.ap_")
|
||||
|
||||
private fun apk(project: Project, flavor: String, suffix: String) : String {
|
||||
val outputDir = dirGet(intermediates(project), "resources", "resources-$flavor")
|
||||
return Paths.get(outputDir, "resources-$flavor.$suffix").toString()
|
||||
}
|
||||
|
||||
private fun intermediates(project: Project) = Paths.get(project.directory, "app", "build", "intermediates")
|
||||
private fun apk(project: Project, flavor: String)
|
||||
= KFiles.joinFileAndMakeDir(project.buildDirectory!!, "outputs", "apk" ,"app-$flavor.apk")
|
||||
|
||||
@Task(name = "generateR", description = "Generate the R.java file",
|
||||
runBefore = arrayOf("compile"), runAfter = arrayOf("clean"))
|
||||
|
@ -119,8 +109,14 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler) :
|
|||
return TaskResult()
|
||||
}
|
||||
|
||||
class AaptCommand(project: Project, aapt: String, val aaptCommand: String,
|
||||
cwd: File = File(project.directory)) : RunCommand(aapt) {
|
||||
open class AndroidCommand(androidHome: String, command: String) : RunCommand(command) {
|
||||
init {
|
||||
env.put("ANDROID_HOME", androidHome)
|
||||
}
|
||||
}
|
||||
|
||||
inner class AaptCommand(project: Project, aapt: String, val aaptCommand: String,
|
||||
cwd: File = File(project.directory)) : AndroidCommand(androidHome(project), aapt) {
|
||||
init {
|
||||
directory = cwd
|
||||
}
|
||||
|
@ -134,7 +130,7 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler) :
|
|||
val manifestDir = Paths.get(project.directory, "app", "src", "main").toString()
|
||||
val manifest = Paths.get(manifestDir, "AndroidManifest.xml")
|
||||
|
||||
val crunchedPngDir = dirGet(intermediates(project), "res", flavor)
|
||||
val crunchedPngDir = KFiles.joinAndMakeDir(intermediates(project).toString(), "res", flavor)
|
||||
|
||||
AaptCommand(project, aapt, "crunch").call(listOf(
|
||||
"-v",
|
||||
|
@ -149,14 +145,16 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler) :
|
|||
"-M", manifest.toString(),
|
||||
"-S", crunchedPngDir,
|
||||
"-S", "app/src/main/res",
|
||||
"-A", dirGet(intermediates(project), "assets", flavor), // where to find more assets
|
||||
// where to find more assets
|
||||
"-A", KFiles.joinAndMakeDir(intermediates(project).toString(), "assets", flavor),
|
||||
"-m", // create directory
|
||||
"-J", dirGet(generated, "sources", "r", flavor).toString(), // where all gets generated
|
||||
// where all gets generated
|
||||
"-J", KFiles.joinAndMakeDir(generated.toString(), "sources", "r", flavor).toString(),
|
||||
"-F", temporaryApk(project, flavor),
|
||||
"--debug-mode",
|
||||
"-0", "apk",
|
||||
"--custom-package", applicationId,
|
||||
"--output-text-symbols", dirGet(intermediates(project), "symbol", flavor))
|
||||
"--output-text-symbols", KFiles.joinAndMakeDir(intermediates(project).toString(), "symbol", flavor))
|
||||
)
|
||||
|
||||
val rDirectory = KFiles.joinDir(generated.toFile().path, "sources", "r", flavor,
|
||||
|
@ -202,21 +200,21 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler) :
|
|||
val buildToolsDir = buildToolsVersion(project)
|
||||
val dx = "${androidHome(project)}/build-tools/$buildToolsDir/dx"
|
||||
val buildDir = context.pluginProperties.get("java", JvmCompilerPlugin.BUILD_DIR)
|
||||
val libsDir = context.pluginProperties.get("packaging", PackagingPlugin.LIBS_DIR)
|
||||
File(libsDir!!.toString()).mkdirs()
|
||||
val libsDir = (context.pluginProperties.get("packaging", PackagingPlugin.LIBS_DIR) as File).path
|
||||
File(libsDir.toString()).mkdirs()
|
||||
val classesDex = "classes.dex"
|
||||
val outClassesDex = KFiles.joinDir(libsDir.toString(), classesDex)
|
||||
val relClassesDex = File(outClassesDex).parentFile
|
||||
RunCommand(dx).run(listOf("--dex", "--output", outClassesDex,
|
||||
buildDir!!.toString()))
|
||||
val classesDexDir = KFiles.joinAndMakeDir(libsDir, "intermediates", "dex", flavor)
|
||||
val outClassesDex = KFiles.joinDir(classesDexDir, classesDex)
|
||||
|
||||
RunCommand(dx).run(listOf("--dex", "--output", outClassesDex, buildDir!!.toString()))
|
||||
|
||||
//
|
||||
// Add classes.dex to existing .ap_
|
||||
//
|
||||
AaptCommand(project, aapt(project), "add", relClassesDex).call(listOf(
|
||||
"-v", temporaryApk(project, flavor), classesDex
|
||||
))
|
||||
AaptCommand(project, aapt(project), "add").apply {
|
||||
directory = File(outClassesDex).parentFile
|
||||
}.call(listOf("-v", KFiles.joinDir("../../../../..", temporaryApk(project, flavor)), classesDex))
|
||||
|
||||
return TaskResult()
|
||||
}
|
||||
|
||||
|
@ -230,7 +228,7 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler) :
|
|||
@Task(name = "signApk", description = "Sign the apk file", runAfter = arrayOf(TASK_GENERATE),
|
||||
runBefore = arrayOf("assemble"))
|
||||
fun signApk(project: Project) : TaskResult {
|
||||
val apk = apk(project, flavor, "apk")
|
||||
val apk = apk(project, flavor)
|
||||
val temporaryApk = temporaryApk(project, flavor)
|
||||
RunCommand("jarsigner").run(listOf(
|
||||
"-keystore", homeDir(".android", "debug.keystore"),
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package com.beust.kobalt.plugin.java
|
||||
|
||||
import com.beust.kobalt.internal.BuildGenerator
|
||||
import com.google.inject.Inject
|
||||
|
||||
public class JavaBuildGenerator @Inject constructor (val projectInfo: JavaProjectInfo) : BuildGenerator() {
|
||||
override val defaultSourceDirectories = projectInfo.defaultSourceDirectories
|
||||
override val defaultTestDirectories = projectInfo.defaultTestDirectories
|
||||
override val directive = "javaProject"
|
||||
override val name = "java"
|
||||
override val fileMatch = { f: String -> f.endsWith(".java") }
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package com.beust.kobalt.plugin.java
|
||||
|
||||
import com.beust.kobalt.api.ICompilerInfo
|
||||
import com.beust.kobalt.misc.KFiles
|
||||
import com.google.inject.Singleton
|
||||
import java.io.File
|
||||
|
||||
@Singleton
|
||||
public class JavaCompilerInfo : ICompilerInfo {
|
||||
override val name = "java"
|
||||
|
||||
override fun findManagedFiles(dir: File) : List<File> {
|
||||
val result = KFiles.findRecursively(dir, { it.endsWith(".java") })
|
||||
.map { File(it) }
|
||||
return result
|
||||
}
|
||||
|
||||
override val defaultSourceDirectories = arrayListOf("src/main/java", "src/main/resources")
|
||||
|
||||
override val defaultTestDirectories = arrayListOf("src/test/java", "src/test/resources")
|
||||
|
||||
override val directive = "javaProject"
|
||||
|
||||
}
|
|
@ -31,11 +31,6 @@ public class JavaPlugin @Inject constructor(
|
|||
override val jvmCompiler: JvmCompiler)
|
||||
: JvmCompilerPlugin(localRepo, files, depFactory, dependencyManager, executors, jvmCompiler),
|
||||
IProjectContributor {
|
||||
|
||||
init {
|
||||
Kobalt.registerCompiler(JavaCompilerInfo())
|
||||
}
|
||||
|
||||
companion object {
|
||||
public const val TASK_COMPILE : String = "compile"
|
||||
public const val TASK_JAVADOC : String = "javadoc"
|
||||
|
|
|
@ -25,7 +25,7 @@ public class JavaProject(
|
|||
@Directive
|
||||
override var packaging: String? = null)
|
||||
: Project(name, version, directory, buildDirectory, group, artifactId, packaging, dependencies,
|
||||
".java", JavaCompilerInfo()) {
|
||||
".java", projectInfo = JavaProjectInfo()) {
|
||||
|
||||
override public fun toString() = toString("JavaProject", "name", name!!)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package com.beust.kobalt.plugin.java
|
||||
|
||||
import com.beust.kobalt.internal.IProjectInfo
|
||||
import com.google.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class JavaProjectInfo : IProjectInfo {
|
||||
override val defaultSourceDirectories = arrayListOf("src/main/java", "src/main/resources")
|
||||
override val defaultTestDirectories = arrayListOf("src/test/java", "src/test/resources")
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.beust.kobalt.plugin.kotlin
|
||||
|
||||
import com.beust.kobalt.internal.BuildGenerator
|
||||
import com.google.inject.Inject
|
||||
|
||||
public class KotlinBuildGenerator @Inject constructor (val projectInfo: KotlinProjectInfo) : BuildGenerator() {
|
||||
override val defaultSourceDirectories = projectInfo.defaultSourceDirectories
|
||||
override val defaultTestDirectories = projectInfo.defaultTestDirectories
|
||||
override val directive = "kotlinProject"
|
||||
override val name = "kotlin"
|
||||
override val fileMatch = { f: String -> f.endsWith(".kt") }
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
package com.beust.kobalt.plugin.kotlin
|
||||
|
||||
import com.beust.kobalt.api.ICompilerInfo
|
||||
import com.beust.kobalt.misc.KFiles
|
||||
import java.io.File
|
||||
|
||||
public class KotlinCompilerInfo : ICompilerInfo {
|
||||
override val name = "kotlin"
|
||||
|
||||
override fun findManagedFiles(dir: File): List<File> {
|
||||
val result = KFiles.findRecursively(dir, { it.endsWith(".kt") })
|
||||
.map { File(it) }
|
||||
return result
|
||||
}
|
||||
|
||||
override val defaultSourceDirectories = arrayListOf("src/main/kotlin", "src/main/resources")
|
||||
|
||||
override val defaultTestDirectories = arrayListOf("src/test/kotlin", "src/test/resources")
|
||||
|
||||
override val directive = "javaProject"
|
||||
}
|
||||
|
|
@ -24,10 +24,6 @@ class KotlinPlugin @Inject constructor(
|
|||
: JvmCompilerPlugin(localRepo, files, depFactory, dependencyManager, executors, jvmCompiler),
|
||||
IProjectContributor, IClasspathContributor {
|
||||
|
||||
init {
|
||||
Kobalt.registerCompiler(KotlinCompilerInfo())
|
||||
}
|
||||
|
||||
companion object {
|
||||
public const val TASK_COMPILE: String = "compile"
|
||||
public const val TASK_COMPILE_TEST: String = "compileTest"
|
||||
|
|
|
@ -25,7 +25,7 @@ public class KotlinProject(
|
|||
@Directive
|
||||
override var packaging: String? = null)
|
||||
: Project(name, version, directory, buildDirectory, group, artifactId, packaging, dependencies, ".kt",
|
||||
KotlinCompilerInfo()) {
|
||||
projectInfo = KotlinProjectInfo()) {
|
||||
|
||||
override public fun toString() = toString("KotlinProject", "name", name!!)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package com.beust.kobalt.plugin.kotlin
|
||||
|
||||
import com.beust.kobalt.internal.IProjectInfo
|
||||
import com.google.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class KotlinProjectInfo : IProjectInfo {
|
||||
override val defaultSourceDirectories = arrayListOf("src/main/kotlin", "src/main/resources")
|
||||
override val defaultTestDirectories = arrayListOf("src/test/kotlin", "src/test/resources")
|
||||
}
|
||||
|
|
@ -9,4 +9,8 @@
|
|||
<class-name>com.beust.kobalt.plugin.java.JavaPlugin</class-name>
|
||||
<class-name>com.beust.kobalt.plugin.kotlin.KotlinPlugin</class-name>
|
||||
</project-contributors>
|
||||
<init-contributors>
|
||||
<class-name>com.beust.kobalt.plugin.java.JavaBuildGenerator</class-name>
|
||||
<class-name>com.beust.kobalt.plugin.kotlin.KotlinBuildGenerator</class-name>
|
||||
</init-contributors>
|
||||
</kobalt-plugin>
|
|
@ -1 +1 @@
|
|||
kobalt.version=0.217
|
||||
kobalt.version=0.219
|
||||
|
|
|
@ -2,11 +2,13 @@ package com.beust.kobalt.maven
|
|||
|
||||
import com.beust.kobalt.Args
|
||||
import com.beust.kobalt.ProjectGenerator
|
||||
import com.beust.kobalt.api.PluginInfo
|
||||
import com.google.inject.Inject
|
||||
import org.testng.Assert
|
||||
import org.testng.annotations.Test
|
||||
import java.io.File
|
||||
|
||||
class PomTest {
|
||||
class PomTest @Inject constructor(val pluginInfo: PluginInfo){
|
||||
@Test
|
||||
fun importPom() {
|
||||
val pomSrc = File("src/test/resources/pom.xml")
|
||||
|
@ -52,13 +54,13 @@ class PomTest {
|
|||
val args = Args()
|
||||
args.buildFile = file.absolutePath
|
||||
args.init = true
|
||||
ProjectGenerator().run(args)
|
||||
ProjectGenerator(pluginInfo).run(args)
|
||||
var contents = file.readText()
|
||||
Assert.assertTrue(contents.contains("group = \"${pom.groupId}\""), "Should find the group defined")
|
||||
Assert.assertTrue(contents.contains("name = \"${pom.name}\""), "Should find the name defined")
|
||||
Assert.assertTrue(contents.contains("version = \"${pom.version}\""), "Should find the version defined")
|
||||
pom.properties.forEach {
|
||||
Assert.assertTrue(contents.contains("val ${ProjectGenerator.translate(it.key)} = \"${it.value}\""), "Should find the " +
|
||||
Assert.assertTrue(contents.contains("val ${ProjectGenerator.toIdentifier(it.key)} = \"${it.value}\""), "Should find the " +
|
||||
"property defined")
|
||||
}
|
||||
pom.repositories.forEach {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue