mirror of
https://github.com/ethauvin/kobalt.git
synced 2025-04-26 16:28:12 -07:00
Support for archetypes.
This commit is contained in:
parent
1821f46e1c
commit
b57b1845bc
9 changed files with 51 additions and 48 deletions
|
@ -29,8 +29,8 @@ class Args {
|
||||||
@Parameter(names = arrayOf("--help", "--usage"), description = "Display the help")
|
@Parameter(names = arrayOf("--help", "--usage"), description = "Display the help")
|
||||||
var usage: Boolean = false
|
var usage: Boolean = false
|
||||||
|
|
||||||
@Parameter(names = arrayOf("-i", "--init"), description = "Create a build file based on the current project")
|
@Parameter(names = arrayOf("-i", "--init"), description = "Invoke the archetypes named, separated by a comma")
|
||||||
var init: Boolean = false
|
var archetypes : String? = null
|
||||||
|
|
||||||
@Parameter(names = arrayOf("--log"), description = "Define the log level (1-3)")
|
@Parameter(names = arrayOf("--log"), description = "Define the log level (1-3)")
|
||||||
var log: Int = 1
|
var log: Int = 1
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
package com.beust.kobalt
|
package com.beust.kobalt
|
||||||
|
|
||||||
|
import com.beust.kobalt.misc.KFiles
|
||||||
|
|
||||||
object Constants {
|
object Constants {
|
||||||
val BUILD_FILE_NAME = "Build.kt"
|
val BUILD_FILE_NAME = "Build.kt"
|
||||||
val BUILD_FILE_DIRECTORY = "kobalt/src"
|
val BUILD_FILE_DIRECTORY = "kobalt/src"
|
||||||
|
val BUILD_FILE_PATH = KFiles.joinDir(BUILD_FILE_DIRECTORY, BUILD_FILE_NAME)
|
||||||
|
|
||||||
internal val DEFAULT_REPOS = listOf(
|
internal val DEFAULT_REPOS = listOf(
|
||||||
"http://repo1.maven.org/maven2/",
|
"http://repo1.maven.org/maven2/",
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
package com.beust.kobalt.api
|
package com.beust.kobalt.api
|
||||||
|
|
||||||
import java.io.OutputStream
|
import com.beust.kobalt.Args
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plugins that want to participate in the --init process (they can generate files to initialize
|
* Plugins that want to participate in the --init process (they can generate files to initialize
|
||||||
* a new project).
|
* a new project).
|
||||||
*/
|
*/
|
||||||
interface IInitContributor<T> : ISimpleAffinity<T> {
|
interface IInitContributor {
|
||||||
/**
|
val name: String
|
||||||
* Generate the Build.kt file into the given OutputStream.
|
|
||||||
*/
|
fun generateArchetype(args: Args)
|
||||||
fun generateBuildFile(os: OutputStream)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ class PluginInfo(val xml: KobaltPluginXml, val classLoader: ClassLoader?) {
|
||||||
val plugins = arrayListOf<IPlugin>()
|
val plugins = arrayListOf<IPlugin>()
|
||||||
val projectContributors = arrayListOf<IProjectContributor>()
|
val projectContributors = arrayListOf<IProjectContributor>()
|
||||||
val classpathContributors = arrayListOf<IClasspathContributor>()
|
val classpathContributors = arrayListOf<IClasspathContributor>()
|
||||||
val initContributors = arrayListOf<IInitContributor<File>>()
|
val initContributors = arrayListOf<IInitContributor>()
|
||||||
val repoContributors = arrayListOf<IRepoContributor>()
|
val repoContributors = arrayListOf<IRepoContributor>()
|
||||||
val compilerFlagContributors = arrayListOf<ICompilerFlagContributor>()
|
val compilerFlagContributors = arrayListOf<ICompilerFlagContributor>()
|
||||||
val compilerInterceptors = arrayListOf<ICompilerInterceptor>()
|
val compilerInterceptors = arrayListOf<ICompilerInterceptor>()
|
||||||
|
@ -147,7 +147,7 @@ class PluginInfo(val xml: KobaltPluginXml, val classLoader: ClassLoader?) {
|
||||||
if (this is ICompilerFlagContributor) compilerFlagContributors.add(this)
|
if (this is ICompilerFlagContributor) compilerFlagContributors.add(this)
|
||||||
if (this is ICompilerInterceptor) compilerInterceptors.add(this)
|
if (this is ICompilerInterceptor) compilerInterceptors.add(this)
|
||||||
if (this is IDocContributor) docContributors.add(this)
|
if (this is IDocContributor) docContributors.add(this)
|
||||||
if (this is IInitContributor<*>) initContributors.add(this as IInitContributor<File>)
|
if (this is IInitContributor) initContributors.add(this as IInitContributor)
|
||||||
if (this is IPlugin) plugins.add(this)
|
if (this is IPlugin) plugins.add(this)
|
||||||
if (this is IProjectContributor) projectContributors.add(this)
|
if (this is IProjectContributor) projectContributors.add(this)
|
||||||
if (this is IRepoContributor) repoContributors.add(this)
|
if (this is IRepoContributor) repoContributors.add(this)
|
||||||
|
|
|
@ -28,6 +28,9 @@ import javax.xml.xpath.XPathFactory
|
||||||
class RepoFinder @Inject constructor(val executors: KobaltExecutors) {
|
class RepoFinder @Inject constructor(val executors: KobaltExecutors) {
|
||||||
fun findCorrectRepo(id: String) = FOUND_REPOS.get(id)
|
fun findCorrectRepo(id: String) = FOUND_REPOS.get(id)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* archiveUrl: full URL
|
||||||
|
*/
|
||||||
data class RepoResult(val hostConfig: HostConfig, val version: Version? = null,
|
data class RepoResult(val hostConfig: HostConfig, val version: Version? = null,
|
||||||
val archiveUrl: String? = null, val snapshotVersion: Version? = null) {
|
val archiveUrl: String? = null, val snapshotVersion: Version? = null) {
|
||||||
val found = archiveUrl != null
|
val found = archiveUrl != null
|
||||||
|
@ -96,7 +99,7 @@ class RepoFinder @Inject constructor(val executors: KobaltExecutors) {
|
||||||
val path = ud.toMetadataXmlPath(false, isLocal)
|
val path = ud.toMetadataXmlPath(false, isLocal)
|
||||||
val foundVersion = findCorrectVersionRelease(path, repoUrl)
|
val foundVersion = findCorrectVersionRelease(path, repoUrl)
|
||||||
if (foundVersion != null) {
|
if (foundVersion != null) {
|
||||||
return RepoResult(repo, Version.of(foundVersion), path)
|
return RepoResult(repo, Version.of(foundVersion), repoUrl + path)
|
||||||
} else {
|
} else {
|
||||||
return RepoResult(repo)
|
return RepoResult(repo)
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,7 @@ private class Main @Inject constructor(
|
||||||
println(AsciiArt.banner + Kobalt.version + "\n")
|
println(AsciiArt.banner + Kobalt.version + "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.init) {
|
if (args.archetypes != null) {
|
||||||
//
|
//
|
||||||
// --init: create a new build project and install the wrapper
|
// --init: create a new build project and install the wrapper
|
||||||
// Make sure the wrapper won't call us back with --noLaunch
|
// Make sure the wrapper won't call us back with --noLaunch
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package com.beust.kobalt.app
|
package com.beust.kobalt.app
|
||||||
|
|
||||||
|
import com.beust.kobalt.Args
|
||||||
import com.beust.kobalt.api.IInitContributor
|
import com.beust.kobalt.api.IInitContributor
|
||||||
import com.beust.kobalt.maven.Pom
|
import com.beust.kobalt.maven.Pom
|
||||||
import com.beust.kobalt.misc.KFiles
|
import com.beust.kobalt.misc.log
|
||||||
import com.github.mustachejava.DefaultMustacheFactory
|
import com.github.mustachejava.DefaultMustacheFactory
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -10,20 +11,35 @@ import java.util.*
|
||||||
/**
|
/**
|
||||||
* Abstract base class for the build generators that use build-template.mustache.
|
* Abstract base class for the build generators that use build-template.mustache.
|
||||||
*/
|
*/
|
||||||
abstract class BuildGenerator : IInitContributor<File> {
|
abstract class BuildGenerator : IInitContributor {
|
||||||
abstract val defaultSourceDirectories : HashSet<String>
|
abstract val defaultSourceDirectories : HashSet<String>
|
||||||
abstract val defaultTestDirectories : HashSet<String>
|
abstract val defaultTestDirectories : HashSet<String>
|
||||||
abstract val directive : String
|
abstract val directive : String
|
||||||
abstract val name : String
|
override abstract val name : String
|
||||||
abstract val fileMatch : (String) -> Boolean
|
abstract val fileMatch : (String) -> Boolean
|
||||||
|
|
||||||
override fun generateBuildFile(os: OutputStream) {
|
companion object {
|
||||||
PrintWriter(os).use {
|
/**
|
||||||
it.print(buildFileContent)
|
* Turns a dot property into a proper Kotlin identifier, e.g. common.version -> commonVersion
|
||||||
|
*/
|
||||||
|
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("")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun affinity(arg: File) = KFiles.findRecursively(arg, fileMatch).size
|
override fun generateArchetype(args: Args) {
|
||||||
|
val file = File(args.buildFile)
|
||||||
|
if (! file.exists()) {
|
||||||
|
PrintWriter(FileOutputStream(file)).use {
|
||||||
|
it.print(buildFileContent)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log(1, "Build file already exists, not overwriting it")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun importPom(pomFile: File, mainDeps: ArrayList<Pom.Dependency>, testDeps: ArrayList<Pom.Dependency>,
|
private fun importPom(pomFile: File, mainDeps: ArrayList<Pom.Dependency>, testDeps: ArrayList<Pom.Dependency>,
|
||||||
map: HashMap<String, Any?>) {
|
map: HashMap<String, Any?>) {
|
||||||
|
@ -37,7 +53,7 @@ abstract class BuildGenerator : IInitContributor<File> {
|
||||||
}
|
}
|
||||||
|
|
||||||
val properties = pom.properties
|
val properties = pom.properties
|
||||||
val mapped = properties.entries.associateBy({ it.key }, { ProjectGenerator.toIdentifier(it.key) })
|
val mapped = properties.entries.associateBy({ it.key }, { toIdentifier(it.key) })
|
||||||
|
|
||||||
map.put("properties", properties.entries.map({ Pair(mapped[it.key], it.value) }))
|
map.put("properties", properties.entries.map({ Pair(mapped[it.key], it.value) }))
|
||||||
|
|
||||||
|
|
|
@ -1,43 +1,23 @@
|
||||||
package com.beust.kobalt.app
|
package com.beust.kobalt.app
|
||||||
|
|
||||||
import com.beust.kobalt.Args
|
import com.beust.kobalt.Args
|
||||||
import com.beust.kobalt.internal.ActorUtils
|
|
||||||
import com.beust.kobalt.internal.PluginInfo
|
import com.beust.kobalt.internal.PluginInfo
|
||||||
import com.beust.kobalt.misc.log
|
import com.beust.kobalt.misc.log
|
||||||
import com.google.inject.Inject
|
import com.google.inject.Inject
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked with --init. Generate a new project.
|
* Invoked with --init. Generate a new project.
|
||||||
*/
|
*/
|
||||||
public class ProjectGenerator @Inject constructor(val pluginInfo: PluginInfo){
|
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 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) {
|
fun run(args: Args) {
|
||||||
val contributor = ActorUtils.selectAffinityActor(pluginInfo.initContributors, File("."))
|
|
||||||
File(args.buildFile).parentFile.mkdirs()
|
File(args.buildFile).parentFile.mkdirs()
|
||||||
if (contributor != null) {
|
args.archetypes?.let { archetypes ->
|
||||||
with(File(args.buildFile)) {
|
val contributors = pluginInfo.initContributors.filter { archetypes.contains(it.name) }
|
||||||
if (exists()) {
|
contributors.forEach {
|
||||||
log(1, "Build file $path already exists, not overwriting it")
|
log(2, "Running archetype ${it.name}")
|
||||||
} else {
|
it.generateArchetype(args)
|
||||||
contributor.generateBuildFile(FileOutputStream(this))
|
|
||||||
log(1, "Created $path")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
log(1, "Couldn't identify project, not generating any build file")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.beust.kobalt.maven
|
||||||
import com.beust.kobalt.Args
|
import com.beust.kobalt.Args
|
||||||
import com.beust.kobalt.KobaltTest
|
import com.beust.kobalt.KobaltTest
|
||||||
import com.beust.kobalt.api.Kobalt
|
import com.beust.kobalt.api.Kobalt
|
||||||
|
import com.beust.kobalt.app.BuildGenerator
|
||||||
import com.beust.kobalt.app.ProjectGenerator
|
import com.beust.kobalt.app.ProjectGenerator
|
||||||
import com.beust.kobalt.internal.PluginInfo
|
import com.beust.kobalt.internal.PluginInfo
|
||||||
import com.google.inject.Inject
|
import com.google.inject.Inject
|
||||||
|
@ -55,7 +56,7 @@ class PomTest @Inject constructor() : KobaltTest() {
|
||||||
file.deleteOnExit()
|
file.deleteOnExit()
|
||||||
val args = Args()
|
val args = Args()
|
||||||
args.buildFile = file.absolutePath
|
args.buildFile = file.absolutePath
|
||||||
args.init = true
|
args.archetypes = "java"
|
||||||
|
|
||||||
ProjectGenerator(Kobalt.INJECTOR.getInstance(PluginInfo::class.java)).run(args)
|
ProjectGenerator(Kobalt.INJECTOR.getInstance(PluginInfo::class.java)).run(args)
|
||||||
|
|
||||||
|
@ -64,8 +65,9 @@ class PomTest @Inject constructor() : KobaltTest() {
|
||||||
Assert.assertTrue(contents.contains("name = \"${pom.name}\""), "Should find the name 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")
|
Assert.assertTrue(contents.contains("version = \"${pom.version}\""), "Should find the version defined")
|
||||||
pom.properties.forEach {
|
pom.properties.forEach {
|
||||||
Assert.assertTrue(contents.contains("val ${ProjectGenerator.toIdentifier(it.key)} = \"${it.value}\""), "Should find the " +
|
Assert.assertTrue(contents.contains(
|
||||||
"property defined")
|
"val ${BuildGenerator.toIdentifier(it.key)} = \"${it.value}\""), "Should find the " +
|
||||||
|
"property defined")
|
||||||
}
|
}
|
||||||
pom.repositories.forEach {
|
pom.repositories.forEach {
|
||||||
Assert.assertTrue(contents.contains(it), "Should find the repository defined")
|
Assert.assertTrue(contents.contains(it), "Should find the repository defined")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue