1
0
Fork 0
mirror of https://github.com/ethauvin/kobalt.git synced 2025-04-26 16:28:12 -07:00
kobalt/src/main/kotlin/com/beust/kobalt/Main.kt

274 lines
9.9 KiB
Kotlin

package com.beust.kobalt
import com.beust.jcommander.JCommander
import com.beust.kobalt.api.IClasspathDependency
import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.api.PluginTask
import com.beust.kobalt.api.Project
import com.beust.kobalt.app.BuildFileCompiler
import com.beust.kobalt.app.MainModule
import com.beust.kobalt.app.ProjectGenerator
import com.beust.kobalt.app.UpdateKobalt
import com.beust.kobalt.app.remote.KobaltClient
import com.beust.kobalt.app.remote.KobaltServer
import com.beust.kobalt.internal.PluginInfo
import com.beust.kobalt.internal.TaskManager
import com.beust.kobalt.internal.build.BuildFile
import com.beust.kobalt.maven.DepFactory
import com.beust.kobalt.maven.Http
import com.beust.kobalt.maven.LocalRepo
import com.beust.kobalt.misc.*
import com.google.common.collect.HashMultimap
import com.google.inject.Guice
import java.io.File
import java.nio.file.Paths
import java.util.*
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException
import javax.inject.Inject
public fun main(argv: Array<String>) {
val result = mainNoExit(argv)
if (result != 0) {
System.exit(result)
}
}
private fun parseArgs(argv: Array<String>): Main.RunInfo {
val args = Args()
val result = JCommander(args)
result.parse(*argv)
KobaltLogger.LOG_LEVEL = args.log
return Main.RunInfo(result, args)
}
public fun mainNoExit(argv: Array<String>): Int {
val (jc, args) = parseArgs(argv)
Kobalt.INJECTOR = Guice.createInjector(MainModule(args))
return Kobalt.INJECTOR.getInstance(Main::class.java).run(jc, args, argv)
}
private class Main @Inject constructor(
val buildFileCompilerFactory: BuildFileCompiler.IFactory,
val plugins: Plugins,
val taskManager: TaskManager,
val http: Http,
val files: KFiles,
val executors: KobaltExecutors,
val localRepo: LocalRepo,
val depFactory: DepFactory,
val checkVersions: CheckVersions,
val github: GithubApi,
val updateKobalt: UpdateKobalt,
val client: KobaltClient,
val server: KobaltServer,
val pluginInfo: PluginInfo,
val projectGenerator: ProjectGenerator,
val resolveDependency: ResolveDependency) {
data class RunInfo(val jc: JCommander, val args: Args)
private fun addReposFromContributors(project: Project?) =
pluginInfo.repoContributors.forEach {
it.reposFor(project).forEach {
Kobalt.addRepo(it)
}
}
public fun run(jc: JCommander, args: Args, argv: Array<String>): Int {
// github.uploadRelease("kobalt", "0.101", File("/Users/beust/t/a.zip"))
//
// Add all the repos from repo contributors (at least those that return values without a Project)
//
addReposFromContributors(null)
//
// Add all the plugins read in kobalt-plugin.xml to the Plugins singleton, so that code
// in the build file that calls Plugins.findPlugin() can find them (code in the
// build file do not have access to the KobaltContext).
//
pluginInfo.plugins.forEach { Plugins.addPluginInstance(it) }
if (args.client) {
client.run()
return 0
}
var result = 0
val latestVersionFuture = github.latestKobaltVersion
val seconds = benchmark {
try {
result = runWithArgs(jc, args, argv)
} catch(ex: KobaltException) {
error("", ex.cause ?: ex)
result = 1
} finally {
executors.shutdown()
}
}
log(1, if (result != 0) "BUILD FAILED: $result" else "BUILD SUCCESSFUL ($seconds seconds)")
// Check for new version
try {
val latestVersionString = latestVersionFuture.get(1, TimeUnit.SECONDS)
val latestVersion = Versions.toLongVersion(latestVersionString)
val current = Versions.toLongVersion(Kobalt.version)
val distFile = File(KFiles.joinDir(KFiles.distributionsDir, latestVersionString))
if (latestVersion > current) {
if (distFile.exists()) {
log(1, "**** Version $latestVersionString is installed")
} else {
listOf("", "New Kobalt version available: $latestVersionString",
"To update, run ./kobaltw --update", "").forEach {
log(1, "**** $it")
}
}
}
} catch(ex: TimeoutException) {
log(2, "Didn't get the new version in time, skipping it")
}
return result
}
// public fun runTest() {
// val file = File("src\\main\\resources\\META-INF\\plugin.ml")
// }
private fun runWithArgs(jc: JCommander, args: Args, argv: Array<String>): Int {
// val file = File("/Users/beust/.kobalt/repository/com/google/guava/guava/19.0-rc2/guava-19.0-rc2.pom")
// val md5 = Md5.toMd5(file)
// val md52 = MessageDigest.getInstance("MD5").digest(file.readBytes()).toHexString()
var result = 0
val p = if (args.buildFile != null) File(args.buildFile) else findBuildFile()
args.buildFile = p.absolutePath
val buildFile = BuildFile(Paths.get(p.absolutePath), p.name)
if (!args.update) {
println(AsciiArt.banner + Kobalt.version + "\n")
}
if (args.init) {
//
// --init: create a new build project and install the wrapper
// Make sure the wrapper won't call us back with --noLaunch
//
com.beust.kobalt.wrapper.Main.main(arrayOf("--noLaunch") + argv)
projectGenerator.run(args)
} else if (args.usage) {
jc.usage()
} else if (args.serverMode) {
server.run()
} else {
if (!buildFile.exists()) {
error(buildFile.path.toFile().path + " does not exist")
} else {
val allProjects = buildFileCompilerFactory.create(listOf(buildFile), pluginInfo)
.compileBuildFiles(args)
//
// Now that we have projects, add all the repos from repo contributors that need a Project
//
allProjects.forEach { addReposFromContributors(it) }
//
// Run all their dependencies through the IDependencyInterceptors
//
runClasspathInterceptors(allProjects)
log(2, "Final list of repos:\n " + Kobalt.repos.joinToString("\n "))
if (args.dependency != null) {
// --resolve
resolveDependency.run(args.dependency as String)
} else if (args.tasks) {
// --tasks
displayTasks()
} else if (args.checkVersions) {
// --checkVersions
checkVersions.run(allProjects)
} else if (args.download) {
// -- download
updateKobalt.downloadKobalt()
} else if (args.update) {
// --update
updateKobalt.updateKobalt()
} else {
//
// Launch the build
//
val thisResult = taskManager.runTargets(args.targets, allProjects)
if (result == 0) {
result = thisResult
}
}
}
}
return result
}
private fun displayTasks() {
//
// List of tasks, --tasks
//
val tasksByPlugins = HashMultimap.create<String, PluginTask>()
taskManager.tasks.forEach {
tasksByPlugins.put(it.plugin.name, it)
}
val sb = StringBuffer("List of tasks\n")
tasksByPlugins.keySet().forEach { name ->
sb.append("\n " + AsciiArt.horizontalDoubleLine + " $name "
+ AsciiArt.horizontalDoubleLine + "\n")
tasksByPlugins[name].distinctBy {
it.name
}.sortedBy {
it.name
}.forEach { task ->
sb.append(" ${task.name}\t\t${task.doc}\n")
}
}
println(sb.toString())
}
private fun runClasspathInterceptors(allProjects: List<Project>) {
allProjects.forEach {
runClasspathInterceptors(it, it.compileDependencies)
runClasspathInterceptors(it, it.compileProvidedDependencies)
runClasspathInterceptors(it, it.compileRuntimeDependencies)
runClasspathInterceptors(it, it.testProvidedDependencies)
runClasspathInterceptors(it, it.testDependencies)
}
}
private fun runClasspathInterceptors(project: Project, dependencies: ArrayList<IClasspathDependency>)
= with(dependencies) {
val deps = interceptDependencies(project, pluginInfo, this)
clear()
addAll(deps)
}
private fun interceptDependencies(project: Project, pluginInfo: PluginInfo,
dependencies: ArrayList<IClasspathDependency>) : ArrayList<IClasspathDependency> {
val result = arrayListOf<IClasspathDependency>()
pluginInfo.classpathInterceptors.forEach {
result.addAll(it.intercept(project, dependencies))
}
return result
}
private fun findBuildFile() : File {
val deprecatedLocation = File(Constants.BUILD_FILE_NAME)
val result: File =
if (deprecatedLocation.exists()) {
warn(Constants.BUILD_FILE_NAME + " is in a deprecated location, please move it to "
+ Constants.BUILD_FILE_DIRECTORY)
deprecatedLocation
} else {
File(KFiles.joinDir(Constants.BUILD_FILE_DIRECTORY, Constants.BUILD_FILE_NAME))
}
return result
}
}