diff --git a/.gitignore b/.gitignore index 881a3193..6d6a56f8 100644 --- a/.gitignore +++ b/.gitignore @@ -2,13 +2,12 @@ annotations .idea/* *.iml -buildScript +nonBuildScript kobaltBuild local.properties classes libs .kobalt/ -./build/ out .DS_Store lib/kotlin-* diff --git a/kobalt/wrapper/kobalt-wrapper.properties b/kobalt/wrapper/kobalt-wrapper.properties index 9f0a84b5..77dee232 100644 --- a/kobalt/wrapper/kobalt-wrapper.properties +++ b/kobalt/wrapper/kobalt-wrapper.properties @@ -1 +1 @@ -kobalt.version=1.0.30 +kobalt.version=1.0.32 diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/ParallelLogger.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/ParallelLogger.kt index 4062c91d..7fda0eac 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/ParallelLogger.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/ParallelLogger.kt @@ -32,17 +32,15 @@ class ParallelLogger @Inject constructor(val args: Args) : ILogger { val newLine: Boolean) private val logLines = ConcurrentHashMap>() - private val runningProjects = ConcurrentLinkedQueue() + private val runningProjects = ConcurrentLinkedQueue() var startTime: Long? = null fun onProjectStarted(name: String) { if (startTime == null) { startTime = System.currentTimeMillis() } - if (! runningProjects.contains(name)) { - runningProjects.add(name) - logLines[name] = arrayListOf() - } + runningProjects.add(name) + logLines[name] = arrayListOf() if (currentName == null) { currentName = name } @@ -76,7 +74,7 @@ class ParallelLogger @Inject constructor(val args: Args) : ILogger { } val LOCK = Any() - var currentName: CharSequence? = null + var currentName: String? = null set(newName) { field = newName } @@ -121,9 +119,6 @@ class ParallelLogger @Inject constructor(val args: Args) : ILogger { if (args.sequential) { kobaltLog(level, message, newLine) } else { - if (! runningProjects.contains(tag)) { - runningProjects.add(tag) - } addLogLine(tag, LogLine(tag, level, message, Type.LOG, newLine)) } } diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/build/BuildFile.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/build/BuildFile.kt index b860f446..a2eb91e9 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/build/BuildFile.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/build/BuildFile.kt @@ -1,10 +1,8 @@ package com.beust.kobalt.internal.build -import com.beust.kobalt.misc.KFiles 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. * @param path is the path where that file was moved, @param realPath is where the actual file is. @@ -12,23 +10,5 @@ import java.nio.file.attribute.BasicFileAttributes class BuildFile(val path: Path, val name: String, val realPath: Path = path) { fun exists() : Boolean = Files.exists(path) - val lastModified : Long - get() = Files.readAttributes(realPath, BasicFileAttributes::class.java).lastModifiedTime().toMillis() - val directory : File get() = path.toFile().parentFile - - /** - * @return the .kobalt directory where this build file will be compiled. - */ - val dotKobaltDir: File get() = File(directory.parentFile.parentFile, KFiles.KOBALT_DOT_DIR).apply { - mkdirs() - } - - /** - * @return the absolute directory of this project's location, assuming the build file is in - * $project/kobalt/src/Build.kt. - */ - val absoluteDir : File? get() { - return path.parent?.parent?.parent?.toFile() - } } diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/build/BuildSources.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/build/BuildSources.kt new file mode 100644 index 00000000..63a8d5be --- /dev/null +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/build/BuildSources.kt @@ -0,0 +1,57 @@ +package com.beust.kobalt.internal.build + +import com.beust.kobalt.homeDir +import java.io.File +import java.nio.file.* +import java.nio.file.attribute.BasicFileAttributes + +interface IBuildSources { + fun findSourceFiles() : List + val root: File + fun exists(): Boolean +} + +class SingleFileBuildSources(val file: File) : IBuildSources { + override fun exists() = file.exists() + override fun findSourceFiles() = listOf(file) + override val root: File = file.parentFile.parentFile +} + +class BuildSources(val file: File) : IBuildSources { + + override val root = file + + override fun findSourceFiles() : List { + return listOf(/* "kobalt/src/a.kt", */ "kobalt/src/Build.kt") + .map(::File) +// .map { BuildFile(Paths.get(it), it)} + } + + override fun exists() = findSourceFiles().isNotEmpty() + + override fun toString() = "{BuildSources " + findSourceFiles()[0] + "...}" + + fun _findSourceFiles() : List { + val result = arrayListOf() + Files.walkFileTree(Paths.get(file.absolutePath), object : SimpleFileVisitor() { + override fun preVisitDirectory(dir: Path?, attrs: BasicFileAttributes?): FileVisitResult { + if (dir != null) { + val path = dir.toFile() + println(path.name) + if (path.name == "src" && path.parentFile.name == "kobalt") { + val sources = path.listFiles().filter { it.name.endsWith(".kt")} + result.addAll(sources) + } + } + + return FileVisitResult.CONTINUE + } + }) + return result + } +} + +fun main(args: Array) { + val sources = BuildSources(File(homeDir("kotlin/kobalt"))).findSourceFiles() + println("sources: " + sources) +} \ No newline at end of file diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/remote/GetDependenciesCommand.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/remote/GetDependenciesCommand.kt deleted file mode 100644 index 7422c493..00000000 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/remote/GetDependenciesCommand.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.beust.kobalt.internal.remote - -import com.beust.kobalt.Constants -import java.io.PrintWriter -import java.net.Socket - -fun main(argv: Array) { - Socket("localhost", 1234).use { socket -> - (PrintWriter(socket.outputStream, true)).use { out -> - out.println("""{ "name" : "getDependencies", "buildFile": - "/Users/beust/kotlin/kobalt/kobalt/src/${Constants.BUILD_FILE_NAME}"}""") - } - } -} \ No newline at end of file diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/BlockExtractor.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/BlockExtractor.kt index c2bdc557..4e92ea2a 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/BlockExtractor.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/BlockExtractor.kt @@ -10,7 +10,18 @@ fun main(argv: Array) { // BlockExtractor("plugins", '(', ')').extractBlock(lines) } -class BuildScriptInfo(val content: String, val startLine: Int, val endLine: Int) +class Section(val start: Int, val end: Int) { + override fun toString() = "$start-$end" +} + +class BuildScriptInfo(val content: String, val sections: List
) { + fun isInSection(lineNumber: Int): Boolean { + sections.forEach { + if (lineNumber >= it.start && lineNumber <= it.end) return true + } + return false + } +} /** * Used to extract a keyword followed by opening and closing tags out of a list of strings, @@ -26,7 +37,7 @@ class BlockExtractor(val regexp: Pattern, val opening: Char, val closing: Char) var foundKeyword = false var foundClosing = false var count = 0 - val result = StringBuffer() + val buildScript = arrayListOf() val topLines = arrayListOf() fun updateCount(line: String) { @@ -46,9 +57,13 @@ class BlockExtractor(val regexp: Pattern, val opening: Char, val closing: Char) if (foundKeyword && count > 0) currentLine.append(c) } - if (currentLine.isNotEmpty()) result.append(currentLine.toString()).append("\n") + if (currentLine.isNotEmpty() && foundKeyword) buildScript.add(currentLine.toString()) } + val allowedImports = listOf("com.beust", "java") + val disallowedImports = listOf("com.beust.kobalt.plugin") + val imports = arrayListOf() + val sections = arrayListOf
() lines.forEach { line -> currentLineNumber++ val found = regexp.matcher(line).matches() @@ -56,26 +71,33 @@ class BlockExtractor(val regexp: Pattern, val opening: Char, val closing: Char) startLine = currentLineNumber foundKeyword = true count = 1 - result.append(topLines.joinToString("\n")).append("\n") - result.append(line).append("\n") + buildScript.add(line) + topLines.add(line) } else { - val allowedImports = listOf("com.beust", "java") - val disallowedImports = listOf("com.beust.kobalt.plugin") - if (! line.startsWith("import") || - (line.startsWith("import") && allowedImports.any { line.contains(it) } - && ! disallowedImports.any { line.contains(it) })) { + if (line.startsWith("import")) { + if (allowedImports.any { line.contains(it) } && !disallowedImports.any { line.contains(it) }) { + imports.add(line) + } + } else { topLines.add(line) } updateCount(line) } if (foundKeyword && foundClosing && count == 0) { - return BuildScriptInfo(result.toString(), startLine, endLine) + sections.add(Section(startLine, endLine)) + foundKeyword = false + foundClosing = false + count = 0 + startLine = 0 + endLine = 0 } } - if (foundKeyword && foundClosing && count == 0) { - return BuildScriptInfo(result.toString(), startLine, endLine) + if (sections.isNotEmpty()) { + val result = (imports.distinct() + buildScript).joinToString("\n") + "\n" + + return BuildScriptInfo(result, sections) } else { return null } diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt index e1e9a709..2fcdbed4 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt @@ -3,7 +3,7 @@ package com.beust.kobalt.misc import com.beust.kobalt.* import com.beust.kobalt.api.Kobalt import com.beust.kobalt.api.Project -import com.beust.kobalt.internal.build.BuildFile +import com.beust.kobalt.internal.build.IBuildSources import com.beust.kobalt.maven.Md5 import java.io.* import java.nio.file.Files @@ -261,10 +261,9 @@ class KFiles { /** * The build location for build scripts is .kobalt/build */ - fun findBuildScriptLocation(buildFile: BuildFile, jarFile: String) : String { - val result = joinDir(buildFile.dotKobaltDir.path, KFiles.SCRIPT_BUILD_DIR, jarFile) - kobaltLog(2, "Build file dotKobaltDir: " + buildFile.dotKobaltDir) - kobaltLog(2, "Script jar file: $result") + fun findBuildScriptLocation(buildSources: IBuildSources, jarFile: String) : String { + val result = joinDir(buildSources.root.path, KFiles.dotKobaltDir.path, KFiles.SCRIPT_BUILD_DIR, jarFile) + kobaltLog(2, " Script jar file: $result") return result } @@ -387,18 +386,7 @@ class KFiles { } } - fun findBuildFile(projectRoot: String = "."): 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(projectRoot, Constants.BUILD_FILE_DIRECTORY, Constants.BUILD_FILE_NAME)) - } - return result - } + val dotKobaltDir = File(KFiles.joinAndMakeDir(KFiles.KOBALT_DOT_DIR)) } fun findRecursively(directory: File, function: Function1): List { diff --git a/src/main/kotlin/com/beust/kobalt/Main.kt b/src/main/kotlin/com/beust/kobalt/Main.kt index 1978ae09..75f27bda 100644 --- a/src/main/kotlin/com/beust/kobalt/Main.kt +++ b/src/main/kotlin/com/beust/kobalt/Main.kt @@ -3,24 +3,17 @@ 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.app.* +import com.beust.kobalt.app.MainModule +import com.beust.kobalt.app.UpdateKobalt import com.beust.kobalt.app.remote.KobaltClient -import com.beust.kobalt.app.remote.KobaltServer -import com.beust.kobalt.app.remote.RemoteDependencyData -import com.beust.kobalt.internal.Gc import com.beust.kobalt.internal.KobaltSettings import com.beust.kobalt.internal.PluginInfo -import com.beust.kobalt.internal.TaskManager -import com.beust.kobalt.internal.build.BuildFile import com.beust.kobalt.maven.DependencyManager import com.beust.kobalt.maven.Http import com.beust.kobalt.maven.dependency.FileDependency import com.beust.kobalt.misc.* -import com.google.common.collect.HashMultimap import java.io.File import java.net.URLClassLoader -import java.nio.file.Paths import javax.inject.Inject fun main(argv: Array) { @@ -56,21 +49,15 @@ fun mainNoExit(argv: Array): Int { private class Main @Inject constructor( val plugins: Plugins, - val taskManager: TaskManager, val http: Http, val files: KFiles, val executors: KobaltExecutors, val dependencyManager: DependencyManager, - val checkVersions: CheckVersions, val github: GithubApi2, val updateKobalt: UpdateKobalt, val client: KobaltClient, val pluginInfo: PluginInfo, - val projectGenerator: ProjectGenerator, - val serverFactory: KobaltServer.IFactory, - val projectFinder: ProjectFinder, - val dependencyData: RemoteDependencyData, - val resolveDependency: ResolveDependency) { + val options: Options) { data class RunInfo(val jc: JCommander, val args: Args) @@ -98,21 +85,20 @@ private class Main @Inject constructor( // // Install plug-ins requested from the command line // - val pluginClassLoader = installCommandLinePlugins(args) + installCommandLinePlugins(args) if (args.client) { client.run() return 0 } - var result = 0 + var result = 1 val latestVersionFuture = github.latestKobaltVersion try { - result = runWithArgs(jc, args, argv, pluginClassLoader) + result = runWithArgs(jc, args, argv) } catch(ex: Throwable) { error("", ex.cause ?: ex) - result = 1 } if (!args.update) { @@ -121,126 +107,16 @@ private class Main @Inject constructor( return result } - private fun runWithArgs(jc: JCommander, args: Args, argv: Array, pluginClassLoader: ClassLoader): 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 KFiles.findBuildFile() + private fun runWithArgs(jc: JCommander, args: Args, argv: Array): Int { + val p = if (args.buildFile != null) File(args.buildFile) else File(".") args.buildFile = p.absolutePath - val buildFile = BuildFile(Paths.get(p.absolutePath), p.name) if (!args.update) { println(AsciiArt.banner + Kobalt.version + "\n") } - if (args.templates != null) { - // - // --init: create a new build project and install the wrapper - // Make sure the wrapper won't call us back with --noLaunch - // - projectGenerator.run(args, pluginClassLoader) - // The wrapper has to call System.exit() in order to set the exit code, - // so make sure we call it last (or possibly launch it in a separate JVM). - com.beust.kobalt.wrapper.Main.main(arrayOf("--noLaunch") + argv) - } else if (args.usage) { - jc.usage() - } else { - // Options that don't need Build.kt to be parsed first - if (args.gc) { - Gc().run() - } else if (args.update) { - // --update - updateKobalt.updateKobalt() - } else if (args.serverMode) { - // --server - val port = serverFactory.create(args.force, args.port, { cleanUp() }).call() - } else { - // - // Everything below requires to parse the build file first - // - if (!buildFile.exists()) { - error(buildFile.path.toFile().path + " does not exist") - } else { - val allProjects = projectFinder.initForBuildFile(buildFile, args) - - addOptionsFromBuild(args, Kobalt.optionsFromBuild) - if (args.listTemplates) { - // --listTemplates - Templates().displayTemplates(pluginInfo) - } else if (args.projectInfo) { - // --projectInfo - allProjects.forEach { - it.compileDependencies.filter { it.isMaven }.forEach { - resolveDependency.run(it.id) - } - } - } else if (args.dependency != null) { - // --resolve - args.dependency?.let { resolveDependency.run(it) } - } else if (args.tasks) { - // --tasks - displayTasks() - } else if (args.checkVersions) { - // --checkVersions - checkVersions.run(allProjects) - } else if (args.download) { - // --download - updateKobalt.downloadKobalt() - } else { - // - // Launch the build - // - val runTargetResult = taskManager.runTargets(args.targets, allProjects) - if (result == 0) { - result = if (runTargetResult.taskResult.success) 0 else 1 - } - - // Shutdown all plug-ins - plugins.shutdownPlugins() - - // Run the build report contributors - pluginInfo.buildReportContributors.forEach { - it.generateReport(Kobalt.context!!) - } - } - } - } - } - return result + return options.run(jc, args, argv) } - private fun addOptionsFromBuild(args: Args, optionsFromBuild: ArrayList) { - optionsFromBuild.forEach { - when(it) { - Args.SEQUENTIAL -> args.sequential = true - else -> throw IllegalArgumentException("Unsupported option found in kobaltOptions(): " + it) - } - } - } - private fun cleanUp() { - pluginInfo.cleanUp() - taskManager.cleanUp() - } - - private fun displayTasks() { - // - // List of tasks, --tasks - // - val tasksByPlugins = HashMultimap.create() - taskManager.annotationTasks.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(PluginTask::name).sortedBy(PluginTask::name).forEach { task -> - sb.append(" ${task.name}\t\t${task.doc}\n") - } - } - - println(sb.toString()) - } } diff --git a/src/main/kotlin/com/beust/kobalt/Options.kt b/src/main/kotlin/com/beust/kobalt/Options.kt index 730321bf..9b29a831 100644 --- a/src/main/kotlin/com/beust/kobalt/Options.kt +++ b/src/main/kotlin/com/beust/kobalt/Options.kt @@ -1,36 +1,58 @@ package com.beust.kobalt import com.beust.jcommander.JCommander +import com.beust.kobalt.api.Kobalt +import com.beust.kobalt.api.PluginTask +import com.beust.kobalt.api.Project +import com.beust.kobalt.app.ProjectFinder import com.beust.kobalt.app.ProjectGenerator +import com.beust.kobalt.app.Templates import com.beust.kobalt.app.UpdateKobalt 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.misc.KFiles +import com.beust.kobalt.internal.build.BuildSources +import com.beust.kobalt.misc.CheckVersions import com.beust.kobalt.wrapper.Main +import com.google.common.collect.HashMultimap import com.google.inject.Inject import java.io.File -import java.nio.file.Paths +/** + * Some options require a build file, others shouldn't have one and some don't care. This + * class captures these requirements. + */ open class Option(open val enabled: () -> Boolean, open val action: () -> Unit, open val requireBuildFile: Boolean = true) class OptionalBuildOption(override val enabled: () -> Boolean, override val action: () -> Unit) : Option(enabled, action, false) class Options @Inject constructor( + val plugins: Plugins, + val checkVersions: CheckVersions, val projectGenerator: ProjectGenerator, val pluginInfo: PluginInfo, val serverFactory: KobaltServer.IFactory, val updateKobalt: UpdateKobalt, - val taskManager: TaskManager + val projectFinder: ProjectFinder, + val taskManager: TaskManager, + val resolveDependency: ResolveDependency ) { - fun run(jc: JCommander, args: Args, argv: Array) { - val p = if (args.buildFile != null) File(args.buildFile) else KFiles.findBuildFile() - val buildFile = BuildFile(Paths.get(p.absolutePath), p.name) + fun run(jc: JCommander, args: Args, argv: Array): Int { + val p = if (args.buildFile != null) File(args.buildFile) else File(".") +// val buildFile = BuildFile(Paths.get(p.absolutePath), p.name) + val buildSources = BuildSources(File(p.absolutePath)) var pluginClassLoader = javaClass.classLoader - val options = arrayListOf