From 50b1ded7bb993c28c918fb2bb4e4cbd3fd310fb0 Mon Sep 17 00:00:00 2001 From: Cedric Beust Date: Wed, 1 Feb 2017 20:47:00 -0800 Subject: [PATCH] Add `isLatest` to nodes returned from the GetDependencies call. --- .../com/beust/kobalt/internal/GraphUtil.kt | 35 ++++++++++++ src/main/kotlin/com/beust/kobalt/Main.kt | 4 +- .../app/remote/GetDependenciesCommand.kt | 2 +- .../app/remote/GetDependencyGraphHandler.kt | 8 +-- .../beust/kobalt/app/remote/JerseyServer.kt | 2 +- .../beust/kobalt/app/remote/KobaltClient.kt | 6 +- .../com/beust/kobalt/app/remote/KobaltHub.kt | 6 +- ...endencyData.kt => RemoteDependencyData.kt} | 55 +++++++++++++++---- .../beust/kobalt/app/remote/SparkServer.kt | 14 ++--- .../beust/kobalt/app/remote/WasabiServer.kt | 2 +- 10 files changed, 101 insertions(+), 33 deletions(-) create mode 100644 modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/GraphUtil.kt rename src/main/kotlin/com/beust/kobalt/app/remote/{DependencyData.kt => RemoteDependencyData.kt} (74%) diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/GraphUtil.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/GraphUtil.kt new file mode 100644 index 00000000..6cef8ada --- /dev/null +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/GraphUtil.kt @@ -0,0 +1,35 @@ +package com.beust.kobalt.internal + +/** + * Generic operations on graph-like structures. + */ +object GraphUtil { + /** + * Apply the operation in `closure` to all the nodes in the tree. + */ + fun map(roots: List, children: (T) -> List, closure: (T) -> Unit) { + roots.forEach { + closure(it) + map(children(it), children, closure) + } + } + + /** + * Display each node in the roots by calling the `display` function on each of them. + */ + fun displayGraph(roots: List, + children: (T) -> List, + display: (node: T, indent: String) -> Unit) { + + fun pd(node: T, indent: String) { + display(node, indent) + children(node).forEach { + pd(it, indent + " ") + } + } + roots.forEach { + pd(it, "") + } + } +} + diff --git a/src/main/kotlin/com/beust/kobalt/Main.kt b/src/main/kotlin/com/beust/kobalt/Main.kt index dda1e8c8..e9ad3737 100644 --- a/src/main/kotlin/com/beust/kobalt/Main.kt +++ b/src/main/kotlin/com/beust/kobalt/Main.kt @@ -5,7 +5,7 @@ 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.remote.DependencyData +import com.beust.kobalt.app.remote.RemoteDependencyData import com.beust.kobalt.app.remote.KobaltClient import com.beust.kobalt.app.remote.KobaltServer import com.beust.kobalt.internal.Gc @@ -69,7 +69,7 @@ private class Main @Inject constructor( val projectGenerator: ProjectGenerator, val serverFactory: KobaltServer.IFactory, val projectFinder: ProjectFinder, - val dependencyData: DependencyData, + val dependencyData: RemoteDependencyData, val resolveDependency: ResolveDependency) { data class RunInfo(val jc: JCommander, val args: Args) diff --git a/src/main/kotlin/com/beust/kobalt/app/remote/GetDependenciesCommand.kt b/src/main/kotlin/com/beust/kobalt/app/remote/GetDependenciesCommand.kt index a46e019a..039fc828 100644 --- a/src/main/kotlin/com/beust/kobalt/app/remote/GetDependenciesCommand.kt +++ b/src/main/kotlin/com/beust/kobalt/app/remote/GetDependenciesCommand.kt @@ -15,7 +15,7 @@ import javax.inject.Inject * The response is a GetDependenciesData. */ @Deprecated(message = "Only used by old server, to be deleted") -class GetDependenciesCommand @Inject constructor(val args: Args, val dependencyData: DependencyData) : ICommand { +class GetDependenciesCommand @Inject constructor(val args: Args, val dependencyData: RemoteDependencyData) : ICommand { override val name = "getDependencies" diff --git a/src/main/kotlin/com/beust/kobalt/app/remote/GetDependencyGraphHandler.kt b/src/main/kotlin/com/beust/kobalt/app/remote/GetDependencyGraphHandler.kt index 841650ba..fd8353fd 100644 --- a/src/main/kotlin/com/beust/kobalt/app/remote/GetDependencyGraphHandler.kt +++ b/src/main/kotlin/com/beust/kobalt/app/remote/GetDependencyGraphHandler.kt @@ -61,7 +61,7 @@ class GetDependencyGraphHandler : WebSocketListener { // Get the dependencies for the requested build file and send progress to the web // socket for each project try { - val dependencyData = getInstance(DependencyData::class.java) + val dependencyData = getInstance(RemoteDependencyData::class.java) val args = getInstance(Args::class.java) val allProjects = projectFinder.initForBuildFile(BuildFile(Paths.get(buildFile), buildFile), @@ -75,16 +75,16 @@ class GetDependencyGraphHandler : WebSocketListener { } catch(ex: Throwable) { Exceptions.printStackTrace(ex) val errorMessage = ex.stackTrace.map { it.toString() }.joinToString("\n

") - DependencyData.GetDependenciesData(errorMessage = errorMessage) + RemoteDependencyData.GetDependenciesData(errorMessage = errorMessage) } finally { SparkServer.cleanUpCallback() eventBus.unregister(busListener) } } else { - DependencyData.GetDependenciesData( + RemoteDependencyData.GetDependenciesData( errorMessage = "buildFile wasn't passed in the query parameter") } - sendWebsocketCommand(s.remote, DependencyData.GetDependenciesData.NAME, result) + sendWebsocketCommand(s.remote, RemoteDependencyData.GetDependenciesData.NAME, result) s.close() } } diff --git a/src/main/kotlin/com/beust/kobalt/app/remote/JerseyServer.kt b/src/main/kotlin/com/beust/kobalt/app/remote/JerseyServer.kt index a94555f2..38a2fc8f 100644 --- a/src/main/kotlin/com/beust/kobalt/app/remote/JerseyServer.kt +++ b/src/main/kotlin/com/beust/kobalt/app/remote/JerseyServer.kt @@ -58,7 +58,7 @@ // @Produces(MediaType.APPLICATION_JSON) // fun getDependencies(@QueryParam("buildFile") buildFile: String) : String { // try { -// val dependencyData = Kobalt.INJECTOR.getInstance(DependencyData::class.java) +// val dependencyData = Kobalt.INJECTOR.getInstance(RemoteDependencyData::class.java) // val args = Kobalt.INJECTOR.getInstance(Args::class.java) // // val projects = JerseyServer.initCallback(buildFile) diff --git a/src/main/kotlin/com/beust/kobalt/app/remote/KobaltClient.kt b/src/main/kotlin/com/beust/kobalt/app/remote/KobaltClient.kt index dd4720c2..8466ff5c 100644 --- a/src/main/kotlin/com/beust/kobalt/app/remote/KobaltClient.kt +++ b/src/main/kotlin/com/beust/kobalt/app/remote/KobaltClient.kt @@ -47,7 +47,7 @@ interface Api { @Deprecated(message = "Replaced with /v1/getDependencies") @POST("/v0/getDependencies") - fun getDependencies(@Query("buildFile") buildFile: String) : Call> + fun getDependencies(@Query("buildFile") buildFile: String) : Call> } class KobaltWebSocketClient : Runnable { @@ -82,8 +82,8 @@ class KobaltWebSocketClient : Runnable { if (wsCommand.errorMessage != null) { warn("Received error message from server: " + wsCommand.errorMessage) } else { - if (wsCommand.commandName == DependencyData.GetDependenciesData.NAME) { - val dd = Gson().fromJson(wsCommand.payload, DependencyData.GetDependenciesData::class.java) + if (wsCommand.commandName == RemoteDependencyData.GetDependenciesData.NAME) { + val dd = Gson().fromJson(wsCommand.payload, RemoteDependencyData.GetDependenciesData::class.java) println("Received dependency data: " + dd.projects.size + " projects" + " error: " + dd.errorMessage) } else if (wsCommand.commandName == ProgressCommand.NAME) { diff --git a/src/main/kotlin/com/beust/kobalt/app/remote/KobaltHub.kt b/src/main/kotlin/com/beust/kobalt/app/remote/KobaltHub.kt index 10ad2677..159b07e3 100644 --- a/src/main/kotlin/com/beust/kobalt/app/remote/KobaltHub.kt +++ b/src/main/kotlin/com/beust/kobalt/app/remote/KobaltHub.kt @@ -15,7 +15,7 @@ import com.google.gson.Gson // } //} -class KobaltHub(val dependencyData: DependencyData) { +class KobaltHub(val dependencyData: RemoteDependencyData) { val args = Args() fun runCommand(n: Int) : String { @@ -35,8 +35,8 @@ class KobaltHub(val dependencyData: DependencyData) { fun main(argv: Array) { Kobalt.init(MainModule(Args(), KobaltSettings.readSettingsXml())) - val dependencyData = Kobalt.INJECTOR.getInstance(DependencyData::class.java) + val dependencyData = Kobalt.INJECTOR.getInstance(RemoteDependencyData::class.java) val json = KobaltHub(dependencyData).runCommand(1) - val dd = Gson().fromJson(json, DependencyData.GetDependenciesData::class.java) + val dd = Gson().fromJson(json, RemoteDependencyData.GetDependenciesData::class.java) println("Data2: $dd") } diff --git a/src/main/kotlin/com/beust/kobalt/app/remote/DependencyData.kt b/src/main/kotlin/com/beust/kobalt/app/remote/RemoteDependencyData.kt similarity index 74% rename from src/main/kotlin/com/beust/kobalt/app/remote/DependencyData.kt rename to src/main/kotlin/com/beust/kobalt/app/remote/RemoteDependencyData.kt index 9a5ec22e..74beb0f5 100644 --- a/src/main/kotlin/com/beust/kobalt/app/remote/DependencyData.kt +++ b/src/main/kotlin/com/beust/kobalt/app/remote/RemoteDependencyData.kt @@ -5,13 +5,16 @@ import com.beust.kobalt.api.IClasspathDependency import com.beust.kobalt.api.Project import com.beust.kobalt.app.BuildFileCompiler import com.beust.kobalt.internal.DynamicGraph +import com.beust.kobalt.internal.GraphUtil 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.MavenId import com.beust.kobalt.maven.dependency.FileDependency import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.KobaltExecutors +import com.beust.kobalt.misc.Versions import com.beust.kobalt.misc.log import com.google.inject.Inject import java.io.File @@ -24,7 +27,7 @@ interface IProgressListener { fun onProgress(progress: Int? = null, message: String? = null) } -class DependencyData @Inject constructor(val executors: KobaltExecutors, val dependencyManager: DependencyManager, +class RemoteDependencyData @Inject constructor(val executors: KobaltExecutors, val dependencyManager: DependencyManager, val buildFileCompilerFactory: BuildFileCompiler.IFactory, val pluginInfo: PluginInfo, val taskManager: TaskManager) { @@ -61,16 +64,47 @@ class DependencyData @Inject constructor(val executors: KobaltExecutors, val dep val d = node.value val dep = dependencyManager.create(d.id) return DependencyData(d.id, scope, dep.jarFile.get().absolutePath, - node.children.map { toDependencyData2(scope, it) }) + children = node.children.map { toDependencyData2(scope, it) }) } fun compileDependenciesGraph(project: Project, name: String): List { - val depLambda = { dep : IClasspathDependency -> dep.directDependencies() } + val depLambda = IClasspathDependency::directDependencies val result = (DynamicGraph.Companion.transitiveClosureGraph(pluginDependencies, depLambda) + DynamicGraph.Companion.transitiveClosureGraph(project.compileDependencies, depLambda) + DynamicGraph.Companion.transitiveClosureGraph(project.compileProvidedDependencies, depLambda)) .map { toDependencyData2("compile", it)} + + fun mapOfLatestVersions(l: List) : Map { + fun p(l: List, latestVersions: HashMap) { + l.forEach { + if (it.id.contains("squareup:okio")) { + println("DONOTCOMMIT") + } + val mid = MavenId.create(it.id) + val shortId = mid.artifactId + ":" + mid.artifactId + val currentLatest = latestVersions[shortId] + if (currentLatest == null) latestVersions[shortId] = mid.version!! + else mid.version?.let { v -> + if (Versions.toLongVersion(currentLatest) < Versions.toLongVersion(v)) { + latestVersions[shortId] = v + } + } + p(it.children, latestVersions) + } + } + val result = hashMapOf() + p(l, result) + return result + } + val map = mapOfLatestVersions(result) + GraphUtil.map(result, { d: DependencyData -> d.children }, + {d: DependencyData -> + val mid = MavenId.create(d.id) + val shortId = mid.artifactId + ":" + mid.artifactId + val version = map[shortId] + d.isLatest = version == mid.version + }) return result } @@ -123,15 +157,13 @@ class DependencyData @Inject constructor(val executors: KobaltExecutors, val dep // log(2, "Returning dependencies:") - fun displayDependencies(header: String, dd: List) { - log(2, " $header:") - if (dd.any()) log(2, " " + dd.map { it.id }.toSortedSet().joinToString("\n ")) - } - projectDatas.forEach { log(2, " Project: " + it.name) - displayDependencies("compileDependencies", it.compileDependencies) - displayDependencies("testDependencies", it.testDependencies) + GraphUtil.displayGraph(it.compileDependencies, + {dd: DependencyData -> dd.children }, + {dd: DependencyData, indent: String -> + println(indent + dd.id + " " + (if (! dd.isLatest) "(old)" else "")) + }) } return GetDependenciesData(projectDatas, allTasks, projectResult.taskResult.errorMessage) @@ -142,8 +174,9 @@ class DependencyData @Inject constructor(val executors: KobaltExecutors, val dep // use these same classes. // - class DependencyData(val id: String, val scope: String, val path: String, + class DependencyData(val id: String, val scope: String, val path: String, var isLatest: Boolean = true, val children: List = emptyList()) + data class TaskData(val name: String, val description: String, val group: String) { override fun toString() = name } diff --git a/src/main/kotlin/com/beust/kobalt/app/remote/SparkServer.kt b/src/main/kotlin/com/beust/kobalt/app/remote/SparkServer.kt index 1ffd448c..8249ea5d 100644 --- a/src/main/kotlin/com/beust/kobalt/app/remote/SparkServer.kt +++ b/src/main/kotlin/com/beust/kobalt/app/remote/SparkServer.kt @@ -72,17 +72,17 @@ class SparkServer(val initCallback: (String) -> List, val cleanUpCallba val result = if (buildFile != null) { try { - val dependencyData = Kobalt.INJECTOR.getInstance(DependencyData::class.java) + val dependencyData = Kobalt.INJECTOR.getInstance(RemoteDependencyData::class.java) val args = Kobalt.INJECTOR.getInstance(Args::class.java) dependencyData.dependenciesDataFor(buildFile, args) } catch(ex: Exception) { - DependencyData.GetDependenciesData(errorMessage = ex.message) + RemoteDependencyData.GetDependenciesData(errorMessage = ex.message) } finally { cleanUpCallback() } } else { - DependencyData.GetDependenciesData( + RemoteDependencyData.GetDependenciesData( errorMessage = "buildFile wasn't passed in the query parameter") } cleanUpCallback() @@ -143,7 +143,7 @@ class GetDependenciesHandler : WebSocketListener { // Get the dependencies for the requested build file and send progress to the web // socket for each project try { - val dependencyData = getInstance(DependencyData::class.java) + val dependencyData = getInstance(RemoteDependencyData::class.java) val args = getInstance(Args::class.java) val allProjects = projectFinder.initForBuildFile(BuildFile(Paths.get(buildFile), buildFile), @@ -157,16 +157,16 @@ class GetDependenciesHandler : WebSocketListener { } catch(ex: Throwable) { ex.printStackTrace() val errorMessage = ex.stackTrace.map { it.toString() }.joinToString("\n

") - DependencyData.GetDependenciesData(errorMessage = errorMessage) + RemoteDependencyData.GetDependenciesData(errorMessage = errorMessage) } finally { SparkServer.cleanUpCallback() eventBus.unregister(busListener) } } else { - DependencyData.GetDependenciesData( + RemoteDependencyData.GetDependenciesData( errorMessage = "buildFile wasn't passed in the query parameter") } - sendWebsocketCommand(s.remote, DependencyData.GetDependenciesData.NAME, result) + sendWebsocketCommand(s.remote, RemoteDependencyData.GetDependenciesData.NAME, result) s.close() } } diff --git a/src/main/kotlin/com/beust/kobalt/app/remote/WasabiServer.kt b/src/main/kotlin/com/beust/kobalt/app/remote/WasabiServer.kt index 93b9eddc..9f2862cd 100644 --- a/src/main/kotlin/com/beust/kobalt/app/remote/WasabiServer.kt +++ b/src/main/kotlin/com/beust/kobalt/app/remote/WasabiServer.kt @@ -15,7 +15,7 @@ // // val projects = initCallback(buildFile) // val result = try { -// val dependencyData = Kobalt.INJECTOR.getInstance(DependencyData::class.java) +// val dependencyData = Kobalt.INJECTOR.getInstance(RemoteDependencyData::class.java) // val args = Kobalt.INJECTOR.getInstance(Args::class.java) // // val dd = dependencyData.dependenciesDataFor(buildFile, args)