diff --git a/tmp/Build.kt b/tmp/Build.kt index 4dc140cd..bc7f53f2 100644 --- a/tmp/Build.kt +++ b/tmp/Build.kt @@ -1,13 +1,19 @@ -import com.beust.kobalt.* -import com.beust.kobalt.api.* +import com.beust.kobalt.TaskResult +import com.beust.kobalt.api.License +import com.beust.kobalt.api.Project +import com.beust.kobalt.api.Scm import com.beust.kobalt.api.annotation.Task +import com.beust.kobalt.homeDir import com.beust.kobalt.plugin.application.application -import com.beust.kobalt.plugin.java.* -import com.beust.kobalt.plugin.kotlin.* +import com.beust.kobalt.plugin.java.javaCompiler +import com.beust.kobalt.plugin.java.javaProject +import com.beust.kobalt.plugin.kotlin.kotlinCompiler +import com.beust.kobalt.plugin.kotlin.kotlinProject import com.beust.kobalt.plugin.packaging.assemble import com.beust.kobalt.plugin.publish.github import com.beust.kobalt.plugin.publish.jcenter +import com.beust.kobalt.repos import com.beust.kobalt.test import java.io.File import java.nio.file.Files @@ -60,8 +66,8 @@ val kobaltPluginApi = kotlinProject { dependencies { compile("org.jetbrains.kotlinx:kotlinx.dom:0.0.4", - "com.beust:jcommander:1.48", "com.squareup.okhttp:okhttp:2.5.0", + "com.squareup.okio:okio:1.6.0", "com.google.inject:guice:4.0", "com.google.inject.extensions:guice-assistedinject:4.0", "javax.inject:javax.inject:1", @@ -69,8 +75,9 @@ val kobaltPluginApi = kotlinProject { "org.apache.maven:maven-model:3.3.3", "io.reactivex:rxjava:1.0.16", "com.google.code.gson:gson:2.4", - "com.squareup.retrofit:retrofit:1.9.0" - ) + "com.squareup.retrofit:retrofit:1.9.0", + "com.beust:jcommander:1.48" + ) } @@ -113,7 +120,20 @@ val kobaltApp = kotlinProject(kobaltPluginApi, wrapper) { "org.jetbrains.dokka:dokka-fatjar:0.9.3") // Used by the main app - compile("com.github.spullara.mustache.java:compiler:0.9.1") + compile("com.github.spullara.mustache.java:compiler:0.9.1", + "com.squareup.okhttp:okhttp:2.5.0", + "javax.inject:javax.inject:1", + "com.google.inject:guice:4.0", + "com.google.inject.extensions:guice-assistedinject:4.0", + "com.beust:jcommander:1.48", + "com.squareup.retrofit:retrofit:1.9.0", + "org.apache.maven:maven-model:3.3.3", + "org.codehaus.plexus:plexus-utils:3.0.22") + + } + + dependenciesTest { + compile("org.testng:testng:6.9.9") } assemble { diff --git a/tmp/DepFactory.kt b/tmp/DepFactory.kt new file mode 100644 index 00000000..48ac619f --- /dev/null +++ b/tmp/DepFactory.kt @@ -0,0 +1,58 @@ +package com.beust.kobalt.maven + +import com.beust.kobalt.KobaltException +import com.beust.kobalt.api.IClasspathDependency +import com.beust.kobalt.api.Kobalt +import com.beust.kobalt.maven.dependency.FileDependency +import com.beust.kobalt.maven.dependency.MavenDependency +import com.beust.kobalt.misc.DependencyExecutor +import com.beust.kobalt.misc.KobaltExecutors +import com.google.inject.Key +import java.util.concurrent.ExecutorService +import javax.inject.Inject + +public class DepFactory @Inject constructor(val localRepo: LocalRepo, + val remoteRepo: RepoFinder, + val executors: KobaltExecutors, + val downloadManager: DownloadManager, + val pomFactory: Pom.IFactory) { + + companion object { + val defExecutor : ExecutorService by lazy { + Kobalt.INJECTOR.getInstance(Key.get(ExecutorService::class.java, DependencyExecutor::class.java)) + } + } + + /** + * Parse the id and return the correct IClasspathDependency + */ + public fun create(id: String, executor: ExecutorService = defExecutor, localFirst : Boolean = true) + : IClasspathDependency { + if (id.startsWith(FileDependency.PREFIX_FILE)) { + return FileDependency(id.substring(FileDependency.PREFIX_FILE.length)) + } else { + val mavenId = MavenId.create(id) + var version = mavenId.version + var packaging = mavenId.packaging + var repoResult: RepoFinder.RepoResult? + + if (version == null || MavenId.isRangedVersion(version)) { + var localVersion: String? = version + if (localFirst) localVersion = localRepo.findLocalVersion(mavenId.groupId, mavenId.artifactId, mavenId.packaging) + if (localFirst && localVersion != null) { + version = localVersion + } else { + repoResult = remoteRepo.findCorrectRepo(id) + if (!repoResult.found) { + throw KobaltException("Couldn't resolve $id") + } else { + version = repoResult.version?.version + } + } + } + + return MavenDependency(MavenId.create(mavenId.groupId, mavenId.artifactId, packaging, version), + executor, localRepo, remoteRepo, pomFactory, downloadManager) + } + } +} diff --git a/tmp/KFiles.kt b/tmp/KFiles.kt new file mode 100644 index 00000000..c27949c7 --- /dev/null +++ b/tmp/KFiles.kt @@ -0,0 +1,300 @@ +package com.beust.kobalt.misc + +import com.beust.kobalt.IFileSpec +import com.beust.kobalt.SystemProperties +import com.beust.kobalt.Variant +import com.beust.kobalt.api.Kobalt +import com.beust.kobalt.api.Project +import com.beust.kobalt.homeDir +import com.beust.kobalt.internal.build.BuildFile +import java.io.File +import java.io.IOException +import java.nio.file.* +import kotlin.io.FileAlreadyExistsException +import kotlin.io.FileSystemException +import kotlin.io.NoSuchFileException + +class KFiles { + /** + * This actually returns a list of strings because in development mode, we are not pointing to a single + * jar file but to a set of /classes directories. + */ + val kobaltJar : List + get() { + val envJar = System.getenv("KOBALT_JAR") + if (envJar != null) { + debug("Using kobalt jar $envJar") + return listOf(File(envJar).absolutePath) + } else { + val jar = joinDir(distributionsDir, Kobalt.version, "kobalt/wrapper/kobalt-" + Kobalt.version + ".jar") + val jarFile = File(jar) + if (jarFile.exists()) { + return listOf(jarFile.absolutePath) + } else { + // Will only happen when building kobalt itself: the jar file might not be in the dist/ directory + // yet since we're currently building it. Instead, use the classes directly + debug("Couldn't find ${jarFile.absolutePath}, using build/classes/main") + val result = listOf("kobalt", "kobalt-plugin-api", "kobalt-wrapper").map { + File(homeDir(KFiles.joinDir("kotlin", "kobalt", "out", "production", it))).absolutePath + } + return result + } + } + } + + init { + File(KOBALT_DOT_DIR).mkdirs() + } + + companion object { + private const val KOBALT_DOT_DIR : String = ".kobalt" + const val KOBALT_DIR : String = "kobalt" + const val KOBALT_BUILD_DIR = "kobaltBuild" + + // Directories under ~/.kobalt + val localRepo = homeDir(KOBALT_DOT_DIR, "repository") + + /** Where all the .zip files are extracted */ + val distributionsDir = homeDir(KOBALT_DOT_DIR, "wrapper", "dist") + + // Directories under ./.kobalt + val SCRIPT_BUILD_DIR : String = "build" + val CLASSES_DIR : String = "classes" + + /** Where build file and support source files go, under KOBALT_DIR */ + private val SRC = "src" + + val TEST_CLASSES_DIR : String = "test-classes" + + private fun generatedDir(project: Project, variant: Variant) + = KFiles.joinDir(project.directory, project.buildDirectory, "generated", variant.toIntermediateDir()) + + fun generatedSourceDir(project: Project, variant: Variant, name: String) = + KFiles.joinDir(project.directory, project.buildDirectory, "generated", "source", name, + variant.toIntermediateDir()) + + fun buildDir(project: Project) = KFiles.makeDir(project.directory, project.buildDirectory) + + /** + * Join the paths elements with the file separator. + */ + fun joinDir(paths: List): String = paths.joinToString(File.separator) + + /** + * Join the paths elements with the file separator. + */ + fun joinDir(vararg ts: String): String = ts.toArrayList().joinToString(File.separator) + + /** + * The paths elements are expected to be a directory. Make that directory and join the + * elements with the file separator. + */ + fun joinAndMakeDir(paths: List) = joinDir(paths).apply { File(this).mkdirs() } + + /** + * The paths elements are expected to be a directory. Make that directory and join the + * elements with the file separator. + */ + fun joinAndMakeDir(vararg ts: String) = joinAndMakeDir(ts.toList()) + + /** + * The paths elements are expected to be a file. Make that parent directory of that file and join the + * elements with the file separator. + */ + fun joinFileAndMakeDir(vararg ts: String) = joinDir(joinAndMakeDir(ts.slice(0..ts.size - 2)), ts[ts.size - 1]) + + fun makeDir(dir: String, s: String? = null) = + (if (s != null) File(dir, s) else File(dir)).apply { mkdirs() } + + fun findRecursively(rootDir: File) : List = + findRecursively(rootDir, arrayListOf(), { s -> true }) + + fun findRecursively(rootDir: File, directories: List, + function: Function1): List { + var result = arrayListOf() + + val allDirs = arrayListOf() + if (directories.isEmpty()) { + allDirs.add(rootDir) + } else { + allDirs.addAll(directories.map { File(rootDir, it.path) }) + } + + val seen = hashSetOf() + allDirs.forEach { dir -> + if (! dir.exists()) { + log(2, "Couldn't find directory $dir") + } else { + val files = findRecursively(dir, function) + files.map { Paths.get(it) }.forEach { + val rel = Paths.get(dir.path).relativize(it) + if (! seen.contains(rel)) { + result.add(File(dir, rel.toFile().path).path) + seen.add(rel) + } else { + log(2, "Skipped file already seen in previous flavor: $rel") + } + } + } + } + // Return files relative to rootDir + val r = result.map { it.substring(rootDir.path.length + 1)} + return r + } + + fun findRecursively(directory: File, function: Function1): List { + var result = arrayListOf() + directory.listFiles().forEach { + if (it.isFile && function(it.path)) { + result.add(it.path) + } else if (it.isDirectory) { + result.addAll(findRecursively(it, function)) + } + } + return result + } + + fun copyRecursively(from: File, to: File, replaceExisting: Boolean = true, deleteFirst: Boolean = false, + onError: (File, IOException) -> OnErrorAction = { file, exception -> throw exception }) { + // Need to wait until copyRecursively supports an overwrite: Boolean = false parameter + // Until then, wipe everything first + if (deleteFirst) to.deleteRecursively() +// to.mkdirs() + hackCopyRecursively(from, to, replaceExisting, onError) + } + + /** Private exception class, used to terminate recursive copying */ + private class TerminateException(file: File) : FileSystemException(file) {} + + /** + * Copy/pasted from kotlin/io/Utils.kt to add support for overwriting. + */ + private fun hackCopyRecursively(from: File, dst: File, + replaceExisting: Boolean, + onError: (File, IOException) -> OnErrorAction = + { file, exception -> throw exception } + ): Boolean { + if (!from.exists()) { + return onError(from, NoSuchFileException(file = from, reason = "The source file doesn't exist")) != + OnErrorAction.TERMINATE + } + try { + // We cannot break for loop from inside a lambda, so we have to use an exception here + for (src in from.walkTopDown().fail { f, e -> if (onError(f, e) == OnErrorAction.TERMINATE) throw TerminateException(f) }) { + if (!src.exists()) { + if (onError(src, NoSuchFileException(file = src, reason = "The source file doesn't exist")) == + OnErrorAction.TERMINATE) + return false + } else { + val relPath = src.relativeTo(from) + val dstFile = File(dst, relPath) + if (dstFile.exists() && !replaceExisting && !(src.isDirectory() && dstFile.isDirectory())) { + if (onError(dstFile, FileAlreadyExistsException(file = src, + other = dstFile, + reason = "The destination file already exists")) == OnErrorAction.TERMINATE) + return false + } else if (src.isDirectory()) { + dstFile.mkdirs() + } else { + if (src.copyTo(dstFile, true) != src.length()) { + if (onError(src, IOException("src.length() != dst.length()")) == OnErrorAction.TERMINATE) + return false + } + } + } + } + return true + } catch (e: TerminateException) { + return false + } + } + + fun findDotDir(startDir: File) : File { + var result = startDir + while (result != null && ! File(result, KOBALT_DOT_DIR).exists()) { + result = result.parentFile + } + if (result == null) { + throw IllegalArgumentException("Couldn't locate $KOBALT_DOT_DIR in $startDir") + } + return File(result, KOBALT_DOT_DIR) + } + + /** + * The build location for build scripts is .kobalt/build + */ + fun findBuildScriptLocation(buildFile: BuildFile, jarFile: String) : String { + val result = joinDir(findDotDir(buildFile.directory).absolutePath, KFiles.SCRIPT_BUILD_DIR, jarFile) + log(2, "Script jar file: $result") + return result + } + + fun saveFile(file: File, text: String) { + file.absoluteFile.parentFile.mkdirs() + file.writeText(text) + log(2, "Wrote $file") + } + + private fun isWindows() = System.getProperty("os.name").contains("Windows"); + + fun copy(from: Path?, to: Path?, option: StandardCopyOption = StandardCopyOption.REPLACE_EXISTING) { + if (isWindows() && to!!.toFile().exists()) { + log(2, "Windows detected, not overwriting ${to}") + } else { + try { + log(2, "Copy from $from to ${to!!}") + Files.copy(from, to, option) + } catch(ex: IOException) { + // Windows is anal about this + log(1, "Couldn't copy $from to $to: ${ex.message}") + } + } + } + + fun createTempFile(suffix : String = "", deleteOnExit: Boolean = false) : File = + File.createTempFile("kobalt", suffix, File(SystemProperties.tmpDir)).let { + if (deleteOnExit) it.deleteOnExit() + return it + } + + fun src(filePath: String): String = KFiles.joinDir(KOBALT_DIR, SRC, filePath) + + fun makeDir(project: Project, suffix: String) : File { + return File(project.directory, project.buildDirectory + File.separator + suffix).apply { mkdirs() } + } + + fun makeOutputDir(project: Project) : File = makeDir(project, KFiles.CLASSES_DIR) + + fun makeOutputTestDir(project: Project) : File = makeDir(project, KFiles.TEST_CLASSES_DIR) + + fun isExcluded(file: File, excludes: List) = isExcluded(file.path, excludes) + + fun isExcluded(file: String, excludes: List) : Boolean { + if (excludes.isEmpty()) { + return false + } else { + val ex = arrayListOf() + excludes.forEach { + ex.add(FileSystems.getDefault().getPathMatcher("glob:${it.spec}")) + } + ex.forEach { + if (it.matches(Paths.get(file))) { + log(3, "Excluding $file") + return true + } + } + } + return false + } + + } + + fun findRecursively(directory: File, function: Function1): List { + return KFiles.findRecursively(directory, function) + } + + fun findRecursively(rootDir: File, directories: List, + function: Function1): List { + return KFiles.findRecursively(rootDir, directories, function) + } +} diff --git a/tmp/create-new-world b/tmp/create-new-world index 1e57db49..4952c197 100755 --- a/tmp/create-new-world +++ b/tmp/create-new-world @@ -19,4 +19,6 @@ done cp /Users/beust/t/kobalt-plugin-api.iml modules/kobalt-plugin-api +cp tmp/Build.kt kobalt/src + # return File(homeDir("kotlin", "kobalt", "classes", "production", "kobalt-plugin-api")).absolutePath