From 299f556fe7240025b72a66b47a2f27c9a5096cf7 Mon Sep 17 00:00:00 2001 From: Cedric Beust Date: Mon, 2 May 2016 03:33:57 -0800 Subject: [PATCH] Dependency fixes. --- .../com/beust/kobalt/internal/TaskManager.kt | 58 ++++++++++++++----- .../beust/kobalt/internal/TaskManagerTest.kt | 37 +++++++++++- 2 files changed, 79 insertions(+), 16 deletions(-) diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/TaskManager.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/TaskManager.kt index 9cc77525..9b39e3f6 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/TaskManager.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/TaskManager.kt @@ -39,7 +39,7 @@ class TaskManager @Inject constructor(val args: Args, /** * Ordering: task1 runs before task 2. */ - fun runBefore(task1: String, task2: String) = runBefore.put(task1, task2) + fun runBefore(task1: String, task2: String) = runBefore.put(task2, task1) /** * Ordering: task2 runs after task 1. @@ -167,41 +167,71 @@ class TaskManager @Inject constructor(val args: Args, val newToProcess = arrayListOf() fun maybeAddEdge(task: T, mm: Multimap, isDependency: Boolean, - reverseEdges: Boolean = false) { + reverseEdges: Boolean = false) : Boolean { + var added = false val taskName = toName(task) mm[taskName]?.forEach { toName -> val addEdge = isDependency || (!isDependency && taskNames.contains(toName)) - log(3, " addEdge: $addEdge taskName: $taskName toName: $toName") if (addEdge) { nodeMap[toName].forEach { to -> if (reverseEdges) { - log(3, " Adding reverse edge $to -> $task it=$toName") + log(3, " Adding reverse edge \"$to\" -> \"$task\" it=\"$toName\"") + added = true result.addEdge(to, task) } else { - log(3, " Adding edge $task -> $to") + log(3, " Adding edge \"$task\" -> \"$to\"") + added = true result.addEdge(task, to) } if (!seen.contains(toName(to))) { - log(3, " New node to process: $to") + log(3, " New node to process: \"$to\"") newToProcess.add(to) } else { - log(3, " Already seen: $to") + log(3, " Already seen: $to") } } } } + return added } + fun reverseMultimap(mm: Multimap) : Multimap { + val result = TreeMultimap.create() + mm.keySet().forEach { key -> + mm[key].forEach { value -> + result.put(value, key) + } + } + return result + } + + // These two maps indicate reversed dependencies so we want to have + // a reverse map for them so we consider all the cases. For example, + // if we are looking at task "a", we want to find all the relationships + // that depend on "a" and also all the relationships that "a" depends on + val invertedReverseDependsOn = reverseMultimap(reverseDependsOn) + val invertedRunBefore = reverseMultimap(runBefore) + val invertedDependsOn = reverseMultimap(dependsOn) + val invertedRunAfter = reverseMultimap(runAfter) + while (toProcess.size > 0) { - log(3, " New batch of nodes to process: $toProcess") + log(3, " New batch of nodes to process: $toProcess") toProcess.forEach { current -> result.addNode(current) seen.add(toName(current)) - maybeAddEdge(current, reverseDependsOn, true, true) - maybeAddEdge(current, dependsOn, true, false) - maybeAddEdge(current, runBefore, false, false) - maybeAddEdge(current, runAfter, false, true) +// if (! maybeAddEdge(current, invertedDependsOn, true, true)) { + maybeAddEdge(current, dependsOn, true, false) +// } +// if (! maybeAddEdge(current, invertedRunAfter, false, true)) { + maybeAddEdge(current, runAfter, false, false) +// } + if (! maybeAddEdge(current, invertedReverseDependsOn, true, false)) { + maybeAddEdge(current, reverseDependsOn, true, true) + } + if (! maybeAddEdge(current, invertedRunBefore, false, false)) { + maybeAddEdge(current, runBefore, false, true) + } } toProcess.clear() toProcess.addAll(newToProcess) @@ -246,7 +276,9 @@ class TaskManager @Inject constructor(val args: Args, class TaskAnnotation(val method: Method, val plugin: IPlugin, val name: String, val description: String, val dependsOn: Array, val reverseDependsOn: Array, val runBefore: Array, val runAfter: Array, - val callable: (Project) -> TaskResult) + val callable: (Project) -> TaskResult) { + override fun toString() = "[TaskAnnotation $name]" + } /** * Invoking a @Task means simply calling the method and returning its returned TaskResult. diff --git a/src/test/kotlin/com/beust/kobalt/internal/TaskManagerTest.kt b/src/test/kotlin/com/beust/kobalt/internal/TaskManagerTest.kt index b50c58aa..35dc1d57 100644 --- a/src/test/kotlin/com/beust/kobalt/internal/TaskManagerTest.kt +++ b/src/test/kotlin/com/beust/kobalt/internal/TaskManagerTest.kt @@ -48,7 +48,7 @@ class TaskManagerTest @Inject constructor(val taskManager: TaskManager) { // KobaltLogger.LOG_LEVEL = 3 val t = runCompileTasks(listOf("compile")) Assert.assertEquals(runCompileTasks(listOf("compile")), listOf("compile", "postCompile")) - Assert.assertEquals(runCompileTasks(listOf("postCompile")), listOf("postCompile")) + Assert.assertEquals(runCompileTasks(listOf("postCompile")), listOf("compile", "postCompile")) Assert.assertEquals(runCompileTasks(listOf("compile", "postCompile")), listOf("compile", "postCompile")) Assert.assertEquals(runCompileTasks(listOf("clean")), listOf("clean", "copyVersion")) Assert.assertEquals(runCompileTasks(listOf("clean", "compile")), listOf("clean", "compile", "copyVersion", @@ -85,6 +85,8 @@ class TaskManagerTest @Inject constructor(val taskManager: TaskManager) { @Test fun exampleInTheDocTest() { +// KobaltLogger.LOG_LEVEL = 3 + Assert.assertEquals(runTasks(listOf("assemble"), dependsOn = TreeMultimap.create().apply { put("assemble", "compile") @@ -136,7 +138,7 @@ class TaskManagerTest @Inject constructor(val taskManager: TaskManager) { runBefore = TreeMultimap.create().apply { put("compile", "example") }), - listOf("clean", "example", "compile")) + listOf("clean", "compile", "example")) Assert.assertEquals(runTasks(listOf("compile", "example"), dependsOn = TreeMultimap.create().apply { @@ -145,7 +147,36 @@ class TaskManagerTest @Inject constructor(val taskManager: TaskManager) { runAfter = TreeMultimap.create().apply { put("compile", "example") }), - listOf("clean", "compile", "example")) + listOf("clean", "example", "compile")) + } + + @Test + fun jacocoTest() { + val runTasks = runTasks(listOf("test"), + dependsOn = TreeMultimap.create().apply { + put("test", "compileTest") + put("test", "compile") + put("compileTest", "compile") + }, + reverseDependsOn = TreeMultimap.create().apply { + put("coverage", "test") + }) + Assert.assertTrue(runTasks[0] == "coverage" && runTasks[1] == "compile" + || runTasks[1] == "coverage" && runTasks[0] == "compile") + Assert.assertEquals(runTasks[2], "compileTest") + Assert.assertEquals(runTasks[3], "test") + } + + @Test + fun simple() { + val runTasks = runTasks(listOf("assemble"), + dependsOn = TreeMultimap.create().apply { + put("assemble", "compile") + }, + reverseDependsOn = TreeMultimap.create().apply { + put("copyVersionForWrapper", "compile") + }) + Assert.assertEquals(runTasks, listOf("copyVersionForWrapper", "compile", "assemble")) } }