From 146d6702c5de2c9037b802f875f66fd9aef0542b Mon Sep 17 00:00:00 2001 From: Cedric Beust Date: Fri, 27 Nov 2015 09:16:12 -0800 Subject: [PATCH] Move files into the internal.build package. --- src/main/kotlin/com/beust/kobalt/Main.kt | 4 +- .../internal/remote/GetDependenciesCommand.kt | 4 +- .../com/beust/kobalt/kotlin/BuildFile.kt | 18 --- .../beust/kobalt/kotlin/BuildFileCompiler.kt | 128 ----------------- .../kobalt/kotlin/internal/BuildScriptUtil.kt | 135 ------------------ .../kobalt/kotlin/internal/ParsedBuildFile.kt | 130 ----------------- .../kobalt/kotlin/internal/VersionFile.kt | 20 --- .../kotlin/com/beust/kobalt/misc/KFiles.kt | 2 +- .../com/beust/kobalt/misc/MainModule.kt | 2 +- 9 files changed, 6 insertions(+), 437 deletions(-) delete mode 100644 src/main/kotlin/com/beust/kobalt/kotlin/BuildFile.kt delete mode 100644 src/main/kotlin/com/beust/kobalt/kotlin/BuildFileCompiler.kt delete mode 100644 src/main/kotlin/com/beust/kobalt/kotlin/internal/BuildScriptUtil.kt delete mode 100644 src/main/kotlin/com/beust/kobalt/kotlin/internal/ParsedBuildFile.kt delete mode 100644 src/main/kotlin/com/beust/kobalt/kotlin/internal/VersionFile.kt diff --git a/src/main/kotlin/com/beust/kobalt/Main.kt b/src/main/kotlin/com/beust/kobalt/Main.kt index c178f63f..3bb35821 100644 --- a/src/main/kotlin/com/beust/kobalt/Main.kt +++ b/src/main/kotlin/com/beust/kobalt/Main.kt @@ -7,8 +7,8 @@ import com.beust.kobalt.internal.PluginInfo import com.beust.kobalt.internal.TaskManager import com.beust.kobalt.internal.remote.KobaltClient import com.beust.kobalt.internal.remote.KobaltServer -import com.beust.kobalt.kotlin.BuildFile -import com.beust.kobalt.kotlin.BuildFileCompiler +import com.beust.kobalt.kotlin.internal.build.BuildFile +import com.beust.kobalt.kotlin.internal.build.BuildFileCompiler import com.beust.kobalt.maven.DepFactory import com.beust.kobalt.maven.Http import com.beust.kobalt.maven.LocalRepo diff --git a/src/main/kotlin/com/beust/kobalt/internal/remote/GetDependenciesCommand.kt b/src/main/kotlin/com/beust/kobalt/internal/remote/GetDependenciesCommand.kt index 9c6aaef4..7d4b8523 100644 --- a/src/main/kotlin/com/beust/kobalt/internal/remote/GetDependenciesCommand.kt +++ b/src/main/kotlin/com/beust/kobalt/internal/remote/GetDependenciesCommand.kt @@ -3,8 +3,8 @@ package com.beust.kobalt.internal.remote import com.beust.kobalt.Args import com.beust.kobalt.api.Project import com.beust.kobalt.internal.PluginInfo -import com.beust.kobalt.kotlin.BuildFile -import com.beust.kobalt.kotlin.BuildFileCompiler +import com.beust.kobalt.kotlin.internal.build.BuildFile +import com.beust.kobalt.kotlin.internal.build.BuildFileCompiler import com.beust.kobalt.maven.DependencyManager import com.beust.kobalt.maven.IClasspathDependency import com.beust.kobalt.maven.MavenDependency diff --git a/src/main/kotlin/com/beust/kobalt/kotlin/BuildFile.kt b/src/main/kotlin/com/beust/kobalt/kotlin/BuildFile.kt deleted file mode 100644 index e2311de4..00000000 --- a/src/main/kotlin/com/beust/kobalt/kotlin/BuildFile.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.beust.kobalt.kotlin - -import java.io.File -import java.nio.file.Files -import java.nio.file.Path -import java.nio.file.attribute.BasicFileAttributes - -/** - * Sometimes, build files are moved to temporary files, so we give them a specific name for clarity. - */ -public class BuildFile(val path: Path, val name: String) { - public fun exists() : Boolean = Files.exists(path) - - public val lastModified : Long - get() = Files.readAttributes(path, BasicFileAttributes::class.java).lastModifiedTime().toMillis() - - public val directory : File get() = path.toFile().directory -} diff --git a/src/main/kotlin/com/beust/kobalt/kotlin/BuildFileCompiler.kt b/src/main/kotlin/com/beust/kobalt/kotlin/BuildFileCompiler.kt deleted file mode 100644 index be5b2698..00000000 --- a/src/main/kotlin/com/beust/kobalt/kotlin/BuildFileCompiler.kt +++ /dev/null @@ -1,128 +0,0 @@ -package com.beust.kobalt.kotlin - -import com.beust.kobalt.Args -import com.beust.kobalt.KobaltException -import com.beust.kobalt.Plugins -import com.beust.kobalt.api.Kobalt -import com.beust.kobalt.api.KobaltContext -import com.beust.kobalt.api.PluginProperties -import com.beust.kobalt.api.Project -import com.beust.kobalt.internal.PluginInfo -import com.beust.kobalt.kotlin.internal.BuildScriptUtil -import com.beust.kobalt.kotlin.internal.ParsedBuildFile -import com.beust.kobalt.kotlin.internal.VersionFile -import com.beust.kobalt.maven.DependencyManager -import com.beust.kobalt.misc.KFiles -import com.beust.kobalt.misc.KobaltExecutors -import com.beust.kobalt.misc.log -import com.beust.kobalt.plugin.kotlin.kotlinCompilePrivate -import com.google.inject.assistedinject.Assisted -import rx.subjects.PublishSubject -import java.io.File -import java.net.URL -import java.nio.file.Paths -import javax.inject.Inject - -/** - * Manage the compilation of Build.kt. There are two passes for this processing: - * 1) Extract the repos() and plugins() statements in a separate .kt and compile it into preBuildScript.jar. - * 2) Actually build the whole Build.kt file after adding to the classpath whatever phase 1 found (plugins, repos) - */ -public class BuildFileCompiler @Inject constructor(@Assisted("buildFiles") val buildFiles: List, - @Assisted val pluginInfo: PluginInfo, val files: KFiles, val plugins: Plugins, - val dependencyManager: DependencyManager, val pluginProperties: PluginProperties, - val executors: KobaltExecutors, val buildScriptUtil: BuildScriptUtil) { - - interface IFactory { - fun create(@Assisted("buildFiles") buildFiles: List, pluginInfo: PluginInfo) : BuildFileCompiler - } - - val observable = PublishSubject.create>() - - private val SCRIPT_JAR = "buildScript.jar" - - fun compileBuildFiles(args: Args): List { - // - // Create the KobaltContext - // - val context = KobaltContext(args) - context.pluginInfo = pluginInfo - context.pluginProperties = pluginProperties - context.dependencyManager = dependencyManager - context.executors = executors - Kobalt.context = context - - // - // Find all the projects in the build file, possibly compiling them - // - val allProjects = findProjects(context) - plugins.applyPlugins(context, allProjects) - - return allProjects - } - - private fun findProjects(context: KobaltContext): List { - val result = arrayListOf() - buildFiles.forEach { buildFile -> - val processBuildFile = parseBuildFile(context, buildFile) - val pluginUrls = processBuildFile.pluginUrls - 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 - // changed in-between - buildScriptJarFile.parentFile.let { dir -> - if (! VersionFile.isSameVersionFile(dir)) { - log(1, "Detected new installation, wiping $dir") - dir.listFiles().map { it.delete() } - } - } - - // Write the modified Build.kt (e.g. maybe profiles were applied) to a temporary file, - // compile it, jar it in buildScript.jar and run it - val modifiedBuildFile = KFiles.createTempFile(".kt") - KFiles.saveFile(modifiedBuildFile, processBuildFile.buildScriptCode) - maybeCompileBuildFile(context, BuildFile(Paths.get(modifiedBuildFile.path), "Modified Build.kt"), - buildScriptJarFile, pluginUrls) - val projects = buildScriptUtil.runBuildScriptJarFile(buildScriptJarFile, pluginUrls, context) - result.addAll(projects) - } - return result - } - - private fun maybeCompileBuildFile(context: KobaltContext, buildFile: BuildFile, buildScriptJarFile: File, - pluginUrls: List) { - log(2, "Running build file ${buildFile.name} jar: $buildScriptJarFile") - - if (buildScriptUtil.isUpToDate(buildFile, buildScriptJarFile)) { - log(2, "Build file is up to date") - } else { - log(2, "Need to recompile ${buildFile.name}") - - buildScriptJarFile.delete() - kotlinCompilePrivate { - classpath(files.kobaltJar) - classpath(pluginUrls.map { it.file }) - sourceFiles(listOf(buildFile.path.toFile().absolutePath)) - output = buildScriptJarFile - }.compile(context = context) - - if (! buildScriptJarFile.exists()) { - throw KobaltException("Could not compile ${buildFile.name}") - } - } - } - - /** - * Generate the script file with only the plugins()/repos() directives and run it. Then return - * - 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 parseBuildFile(context: KobaltContext, buildFile: BuildFile) : ParsedBuildFile { - // Parse the build file so we can generate preBuildScript and buildScript from it. - with(ParsedBuildFile(buildFile, context, buildScriptUtil, dependencyManager, files)) { - // Notify possible listeners (e.g. KobaltServer) we now have all the projects - observable.onNext(projects) - return this - } - } -} diff --git a/src/main/kotlin/com/beust/kobalt/kotlin/internal/BuildScriptUtil.kt b/src/main/kotlin/com/beust/kobalt/kotlin/internal/BuildScriptUtil.kt deleted file mode 100644 index f3b373a5..00000000 --- a/src/main/kotlin/com/beust/kobalt/kotlin/internal/BuildScriptUtil.kt +++ /dev/null @@ -1,135 +0,0 @@ -package com.beust.kobalt.kotlin.internal - -import com.beust.kobalt.KobaltException -import com.beust.kobalt.Plugins -import com.beust.kobalt.api.IPlugin -import com.beust.kobalt.api.KobaltContext -import com.beust.kobalt.api.Project -import com.beust.kobalt.api.annotation.Task -import com.beust.kobalt.kotlin.BuildFile -import com.beust.kobalt.misc.KFiles -import com.beust.kobalt.misc.Topological -import com.beust.kobalt.misc.log -import com.google.inject.Inject -import java.io.File -import java.io.FileInputStream -import java.io.InputStream -import java.lang.reflect.Modifier -import java.net.URL -import java.net.URLClassLoader -import java.util.* -import java.util.jar.JarInputStream - -class BuildScriptUtil @Inject constructor(val plugins: Plugins, val files: KFiles){ - val projects = arrayListOf() - - /** - * Run the given preBuildScript (or buildScript) jar file, using a classloader made of the passed URL's. - * This list is empty when we run preBuildScript.jar but for buildScript.jar, it contains the list of - * URL's found from running preBuildScript.jar. - */ - fun runBuildScriptJarFile(buildScriptJarFile: File, urls: List, - context: KobaltContext) : List { - var stream : InputStream? = null - val allUrls = (urls + arrayOf( - buildScriptJarFile.toURI().toURL()) + File(files.kobaltJar).toURI().toURL()) - .toTypedArray() - val classLoader = URLClassLoader(allUrls) - - // - // Install all the plugins - // - plugins.installPlugins(Plugins.dynamicPlugins, classLoader) - - // - // Classload all the jar files and invoke their methods - // - try { - stream = JarInputStream(FileInputStream(buildScriptJarFile)) - var entry = stream.nextJarEntry - - val classes = hashSetOf>() - while (entry != null) { - val name = entry.name; - if (name.endsWith(".class")) { - val className = name.substring(0, name.length - 6).replace("/", ".") - var cl : Class<*>? = classLoader.loadClass(className) - if (cl != null) { - classes.add(cl) - } else { - throw KobaltException("Couldn't instantiate $className") - } - } - entry = stream.nextJarEntry; - } - - // Invoke all the "val" found on the _DefaultPackage class (the Build.kt file) - classes.filter { cls -> - cls.name != "_DefaultPackage" - }.forEach { cls -> - cls.methods.forEach { method -> - // Invoke vals and see if they return a Project - if (method.name.startsWith("get") && Modifier.isStatic(method.modifiers)) { - try { - val r = method.invoke(null) - if (r is Project) { - log(2, "Found project $r in class $cls") - projects.add(r) - } - } catch(ex: Throwable) { - throw ex.cause ?: KobaltException(ex) - } - } else { - val taskAnnotation = method.getAnnotation(Task::class.java) - if (taskAnnotation != null) { - Plugins.defaultPlugin.methodTasks.add(IPlugin.MethodTask(method, taskAnnotation)) - } - - }} - } - } finally { - stream?.close() - } - - validateProjects(projects) - - // - // Now that the build file has run, fetch all the project contributors, grab the projects from them and sort - // them topologically - // - Topological().let { topologicalProjects -> - val all = hashSetOf() - context.pluginInfo.projectContributors.forEach { contributor -> - val descriptions = contributor.projects() - descriptions.forEach { pd -> - all.add(pd.project) - pd.dependsOn.forEach { dependsOn -> - topologicalProjects.addEdge(pd.project, dependsOn) - all.add(dependsOn) - } - } - } - val result = topologicalProjects.sort(ArrayList(all)) - - return result - } - } - - fun isUpToDate(buildFile: BuildFile, jarFile: File) = - buildFile.exists() && jarFile.exists() - && buildFile.lastModified < jarFile.lastModified() - - /** - * Make sure all the projects have a unique name. - */ - private fun validateProjects(projects: List) { - val seen = hashSetOf() - projects.forEach { - if (seen.contains(it.name)) { - throw KobaltException("Duplicate project name: $it") - } else { - seen.add(it.name) - } - } - } -} diff --git a/src/main/kotlin/com/beust/kobalt/kotlin/internal/ParsedBuildFile.kt b/src/main/kotlin/com/beust/kobalt/kotlin/internal/ParsedBuildFile.kt deleted file mode 100644 index 6eea86f7..00000000 --- a/src/main/kotlin/com/beust/kobalt/kotlin/internal/ParsedBuildFile.kt +++ /dev/null @@ -1,130 +0,0 @@ -package com.beust.kobalt.kotlin.internal - -import com.beust.kobalt.Plugins -import com.beust.kobalt.api.KobaltContext -import com.beust.kobalt.api.Project -import com.beust.kobalt.kotlin.BuildFile -import com.beust.kobalt.maven.DependencyManager -import com.beust.kobalt.misc.KFiles -import com.beust.kobalt.misc.countChar -import com.beust.kobalt.misc.log -import com.beust.kobalt.plugin.kotlin.kotlinCompilePrivate -import java.io.File -import java.net.URL -import java.nio.charset.Charset -import java.nio.file.Paths -import java.util.* - -class ParsedBuildFile(val buildFile: BuildFile, val context: KobaltContext, val buildScriptUtil: BuildScriptUtil, - val dependencyManager: DependencyManager, val files: KFiles) { - val pluginList = arrayListOf() - val repos = arrayListOf() - val profileLines = arrayListOf() - val pluginUrls = arrayListOf() - val projects = arrayListOf() - - private val preBuildScript = arrayListOf( - "import com.beust.kobalt.*", - "import com.beust.kobalt.api.*") - val preBuildScriptCode : String get() = preBuildScript.joinToString("\n") - - private val buildScript = arrayListOf() - val buildScriptCode : String get() = buildScript.joinToString("\n") - - init { - parseBuildFile() - initPluginUrls() - } - - private fun parseBuildFile() { - var parenCount = 0 - buildFile.path.toFile().forEachLine(Charset.defaultCharset()) { line -> - var current: ArrayList? = null - var index = line.indexOf("plugins(") - if (index >= 0) { - current = pluginList - } 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 { - 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) } - pluginList.forEach { preBuildScript.add(it) } - } - - private fun initPluginUrls() { - // - // 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(preBuildScriptCode, Charset.defaultCharset()) - log(2, "Saved ${pluginSourceFile.absolutePath}") - - // - // Compile to preBuildScript.jar - // - val buildScriptJar = KFiles.findBuildScriptLocation(buildFile, "preBuildScript.jar") - val buildScriptJarFile = File(buildScriptJar) - if (! buildScriptUtil.isUpToDate(buildFile, File(buildScriptJar))) { - buildScriptJarFile.parentFile.mkdirs() - generateJarFile(context, BuildFile(Paths.get(pluginSourceFile.path), "Plugins"), buildScriptJarFile) - VersionFile.generateVersionFile(buildScriptJarFile.parentFile) - } - - // - // Run preBuildScript.jar to initialize plugins and repos - // - projects.addAll(buildScriptUtil.runBuildScriptJarFile(buildScriptJarFile, arrayListOf(), context)) - - // - // All the plug-ins are now in Plugins.dynamicPlugins, download them if they're not already - // - Plugins.dynamicPlugins.forEach { - pluginUrls.add(it.jarFile.get().toURI().toURL()) - } - } - - private fun generateJarFile(context: KobaltContext, buildFile: BuildFile, buildScriptJarFile: File) { - val kotlintDeps = dependencyManager.calculateDependencies(null, context) - val deps: List = kotlintDeps.map { it.jarFile.get().absolutePath } - kotlinCompilePrivate { - classpath(files.kobaltJar) - classpath(deps) - sourceFiles(buildFile.path.toFile().absolutePath) - output = File(buildScriptJarFile.absolutePath) - }.compile(context = context) - } -} - diff --git a/src/main/kotlin/com/beust/kobalt/kotlin/internal/VersionFile.kt b/src/main/kotlin/com/beust/kobalt/kotlin/internal/VersionFile.kt deleted file mode 100644 index c9d4aa4f..00000000 --- a/src/main/kotlin/com/beust/kobalt/kotlin/internal/VersionFile.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.beust.kobalt.kotlin.internal - -import com.beust.kobalt.api.Kobalt -import com.beust.kobalt.misc.KFiles -import java.io.File - -class VersionFile { - companion object { - private val VERSION_FILE = "version.txt" - - fun generateVersionFile(directory: File) { - KFiles.saveFile(File(directory, VERSION_FILE), Kobalt.version) - } - - fun isSameVersionFile(directory: File) = - with(File(directory, VERSION_FILE)) { - ! exists() || (exists() && readText() == Kobalt.version) - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt b/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt index e11be3c6..4e5b53de 100644 --- a/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt +++ b/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt @@ -3,7 +3,7 @@ package com.beust.kobalt.misc import com.beust.kobalt.SystemProperties import com.beust.kobalt.api.Kobalt import com.beust.kobalt.homeDir -import com.beust.kobalt.kotlin.BuildFile +import com.beust.kobalt.kotlin.internal.build.BuildFile import java.io.File import java.io.IOException import java.nio.file.Files diff --git a/src/main/kotlin/com/beust/kobalt/misc/MainModule.kt b/src/main/kotlin/com/beust/kobalt/misc/MainModule.kt index 6a4e538a..179398f1 100644 --- a/src/main/kotlin/com/beust/kobalt/misc/MainModule.kt +++ b/src/main/kotlin/com/beust/kobalt/misc/MainModule.kt @@ -2,7 +2,7 @@ package com.beust.kobalt.misc import com.beust.kobalt.Args import com.beust.kobalt.internal.PluginInfo -import com.beust.kobalt.kotlin.BuildFileCompiler +import com.beust.kobalt.kotlin.internal.build.BuildFileCompiler import com.beust.kobalt.maven.* import com.beust.kobalt.plugin.publish.JCenterApi import com.google.inject.*