1
0
Fork 0
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:
Cedric Beust 2016-02-11 21:20:29 -08:00
parent 1821f46e1c
commit b57b1845bc
9 changed files with 51 additions and 48 deletions

View file

@ -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

View file

@ -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/",

View file

@ -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)
} }

View file

@ -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)

View file

@ -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)
} }

View file

@ -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

View file

@ -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) }))

View file

@ -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")
} }
} }
} }

View 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")