1
0
Fork 0
mirror of https://github.com/ethauvin/kobalt.git synced 2025-04-26 16:28:12 -07:00

Revamp the graph dependency/ordering logic.

This commit is contained in:
Cedric Beust 2016-04-18 02:51:29 -08:00
parent 2dd20b43b1
commit 458b40eafc
10 changed files with 128 additions and 175 deletions

View file

@ -11,7 +11,8 @@ interface ITaskContributor : IContributor {
} }
class DynamicTask(val plugin: IPlugin, val name: String, val description: String = "", class DynamicTask(val plugin: IPlugin, val name: String, val description: String = "",
val dependsOn: List<String> = listOf<String>(),
val reverseDependsOn: List<String> = listOf<String>(),
val runBefore: List<String> = listOf<String>(), val runBefore: List<String> = listOf<String>(),
val runAfter: List<String> = listOf<String>(), val runAfter: List<String> = listOf<String>(),
val alwaysRunAfter: List<String> = listOf<String>(),
val closure: (Project) -> TaskResult) val closure: (Project) -> TaskResult)

View file

@ -23,16 +23,18 @@ class TaskContributor @Inject constructor(val incrementalManagerFactory: Increme
* depends on variants of that task. * depends on variants of that task.
*/ */
fun addVariantTasks(plugin: IPlugin, project: Project, context: KobaltContext, taskName: String, fun addVariantTasks(plugin: IPlugin, project: Project, context: KobaltContext, taskName: String,
dependsOn: List<String> = emptyList(),
reverseDependsOn : List<String> = emptyList(),
runBefore : List<String> = emptyList(), runBefore : List<String> = emptyList(),
runAfter : List<String> = emptyList(), runAfter : List<String> = emptyList(),
alwaysRunAfter : List<String> = emptyList(),
runTask: (Project) -> TaskResult) { runTask: (Project) -> TaskResult) {
Variant.allVariants(project).forEach { variant -> Variant.allVariants(project).forEach { variant ->
val variantTaskName = variant.toTask(taskName) val variantTaskName = variant.toTask(taskName)
dynamicTasks.add(DynamicTask(plugin, variantTaskName, variantTaskName, dynamicTasks.add(DynamicTask(plugin, variantTaskName, variantTaskName,
dependsOn = dependsOn.map { variant.toTask(it) },
reverseDependsOn = reverseDependsOn.map { variant.toTask(it) },
runBefore = runBefore.map { variant.toTask(it) }, runBefore = runBefore.map { variant.toTask(it) },
runAfter = runAfter.map { variant.toTask(it) }, runAfter = runAfter.map { variant.toTask(it) },
alwaysRunAfter = alwaysRunAfter.map { variant.toTask(it) },
closure = { p: Project -> closure = { p: Project ->
context.variant = variant context.variant = variant
runTask(project) runTask(project)
@ -41,16 +43,18 @@ class TaskContributor @Inject constructor(val incrementalManagerFactory: Increme
} }
fun addIncrementalVariantTasks(plugin: IPlugin, project: Project, context: KobaltContext, taskName: String, fun addIncrementalVariantTasks(plugin: IPlugin, project: Project, context: KobaltContext, taskName: String,
dependsOn: List<String> = emptyList(),
reverseDependsOn : List<String> = emptyList(),
runBefore : List<String> = emptyList(), runBefore : List<String> = emptyList(),
runAfter : List<String> = emptyList(), runAfter : List<String> = emptyList(),
alwaysRunAfter : List<String> = emptyList(),
runTask: (Project) -> IncrementalTaskInfo) { runTask: (Project) -> IncrementalTaskInfo) {
Variant.allVariants(project).forEach { variant -> Variant.allVariants(project).forEach { variant ->
val variantTaskName = variant.toTask(taskName) val variantTaskName = variant.toTask(taskName)
dynamicTasks.add(DynamicTask(plugin, variantTaskName, variantTaskName, dynamicTasks.add(DynamicTask(plugin, variantTaskName, variantTaskName,
dependsOn = dependsOn.map { variant.toTask(it) },
reverseDependsOn = reverseDependsOn.map { variant.toTask(it) },
runBefore = runBefore.map { variant.toTask(it) }, runBefore = runBefore.map { variant.toTask(it) },
runAfter = runAfter.map { variant.toTask(it) }, runAfter = runAfter.map { variant.toTask(it) },
alwaysRunAfter = alwaysRunAfter.map { variant.toTask(it) },
closure = incrementalManagerFactory.create().toIncrementalTaskClosure(taskName, runTask, variant))) closure = incrementalManagerFactory.create().toIncrementalTaskClosure(taskName, runTask, variant)))
} }
} }

View file

@ -11,14 +11,17 @@ annotation class Task(
val name: String, val name: String,
val description: String = "", val description: String = "",
/** Tasks that this task depends on */ /** Dependency: tasks this task depends on */
val dependsOn: Array<String> = arrayOf(),
/** Dependency: tasks this task will be made dependend upon */
val reverseDependsOn: Array<String> = arrayOf(),
/** Ordering: tasks that need to be run before this one */
val runBefore: Array<String> = arrayOf(), val runBefore: Array<String> = arrayOf(),
/** Tasks that this task will run after if they get run */ /** Ordering: tasks this task runs after */
val runAfter: Array<String> = arrayOf(), val runAfter: Array<String> = arrayOf(),
/** Tasks that this task will always run after */
val alwaysRunAfter: Array<String> = arrayOf()
) )
@Retention(AnnotationRetention.RUNTIME) @Retention(AnnotationRetention.RUNTIME)
@ -26,14 +29,17 @@ annotation class IncrementalTask(
val name: String, val name: String,
val description: String = "", val description: String = "",
/** Dependency: tasks this task depends on */
val dependsOn: Array<String> = arrayOf(),
/** Dependency: tasks this task will be made dependend upon */
val reverseDependsOn: Array<String> = arrayOf(),
/** Tasks that this task depends on */ /** Tasks that this task depends on */
val runBefore: Array<String> = arrayOf(), val runBefore: Array<String> = arrayOf(),
/** Tasks that this task will run after if they get run */ /** Ordering: tasks this task runs after */
val runAfter: Array<String> = arrayOf(), val runAfter: Array<String> = arrayOf(),
/** Tasks that this task will always run after */
val alwaysRunAfter: Array<String> = arrayOf()
) )
/** /**

View file

@ -24,7 +24,7 @@ class Node<T>(val value: T) {
} }
class DynamicGraph<T> { class DynamicGraph<T> {
val VERBOSE = 1 val VERBOSE = 2
val values : Collection<T> get() = nodes.map { it.value } val values : Collection<T> get() = nodes.map { it.value }
val nodes = hashSetOf<Node<T>>() val nodes = hashSetOf<Node<T>>()
private val dependedUpon = HashMultimap.create<Node<T>, Node<T>>() private val dependedUpon = HashMultimap.create<Node<T>, Node<T>>()

View file

@ -78,7 +78,7 @@ open class JvmCompilerPlugin @Inject constructor(
val taskName = if (config.name.isEmpty()) "test" else "test" + config.name val taskName = if (config.name.isEmpty()) "test" else "test" + config.name
taskManager.addTask(this, project, taskName, taskManager.addTask(this, project, taskName,
runAfter = listOf(JvmCompilerPlugin.TASK_COMPILE, JvmCompilerPlugin.TASK_COMPILE_TEST), dependsOn = listOf(JvmCompilerPlugin.TASK_COMPILE, JvmCompilerPlugin.TASK_COMPILE_TEST),
task = { taskTest(project, config.name)} ) task = { taskTest(project, config.name)} )
} }
@ -140,7 +140,7 @@ open class JvmCompilerPlugin @Inject constructor(
} }
@IncrementalTask(name = TASK_COMPILE_TEST, description = "Compile the tests", @IncrementalTask(name = TASK_COMPILE_TEST, description = "Compile the tests",
runAfter = arrayOf(TASK_COMPILE)) dependsOn = arrayOf(TASK_COMPILE))
fun taskCompileTest(project: Project): IncrementalTaskInfo { fun taskCompileTest(project: Project): IncrementalTaskInfo {
sourceTestDirectories.addAll(context.variant.sourceDirectories(project, context, SourceSet.of(isTest = true))) sourceTestDirectories.addAll(context.variant.sourceDirectories(project, context, SourceSet.of(isTest = true)))
return IncrementalTaskInfo( return IncrementalTaskInfo(

View file

@ -21,30 +21,32 @@ import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
public class TaskManager @Inject constructor(val args: Args, class TaskManager @Inject constructor(val args: Args,
val incrementalManagerFactory: IncrementalManager.IFactory) { val incrementalManagerFactory: IncrementalManager.IFactory) {
private val dependsOn = TreeMultimap.create<String, String>()
private val reverseDependsOn = TreeMultimap.create<String, String>()
private val runBefore = TreeMultimap.create<String, String>() private val runBefore = TreeMultimap.create<String, String>()
private val runAfter = TreeMultimap.create<String, String>() private val runAfter = TreeMultimap.create<String, String>()
private val alwaysRunAfter = TreeMultimap.create<String, String>()
/** /**
* Called by plugins to indicate task dependencies defined at runtime. Keys depend on values. * Dependency: task2 depends on task 1.
* Declare that `task1` depends on `task2`.
*
* Note: there is no runAfter on this class since a runAfter(a, b) in a task simply translates
* to a runBefore(b, a) here.
*/ */
fun runBefore(task1: String, task2: String) { fun dependsOn(task1: String, task2: String) = dependsOn.put(task2, task1)
runBefore.put(task1, task2)
}
fun runAfter(task1: String, task2: String) { /**
runAfter.put(task1, task2) * Dependency: task2 depends on task 1.
} */
fun reverseDependsOn(task1: String, task2: String) = reverseDependsOn.put(task1, task2)
fun alwaysRunAfter(task1: String, task2: String) { /**
alwaysRunAfter.put(task1, task2) * Ordering: task1 runs before task 2.
} */
fun runBefore(task1: String, task2: String) = runBefore.put(task1, task2)
/**
* Ordering: task2 runs after task 1.
*/
fun runAfter(task1: String, task2: String) = runAfter.put(task2, task1)
data class TaskInfo(val id: String) { data class TaskInfo(val id: String) {
constructor(project: String, task: String) : this(project + ":" + task) constructor(project: String, task: String) : this(project + ":" + task)
@ -58,7 +60,7 @@ public class TaskManager @Inject constructor(val args: Args,
class RunTargetResult(val exitCode: Int, val messages: List<String>) class RunTargetResult(val exitCode: Int, val messages: List<String>)
public fun runTargets(taskNames: List<String>, projects: List<Project>) : RunTargetResult { fun runTargets(taskNames: List<String>, projects: List<Project>) : RunTargetResult {
var result = 0 var result = 0
val failedProjects = hashSetOf<String>() val failedProjects = hashSetOf<String>()
val messages = Collections.synchronizedList(arrayListOf<String>()) val messages = Collections.synchronizedList(arrayListOf<String>())
@ -94,7 +96,7 @@ public class TaskManager @Inject constructor(val args: Args,
} }
val graph = createGraph(project.name, taskNames, tasksByNames, val graph = createGraph(project.name, taskNames, tasksByNames,
runBefore, runAfter, alwaysRunAfter, dependsOn, reverseDependsOn, runBefore, runAfter,
{ task: PluginTask -> task.name }, { task: PluginTask -> task.name },
{ task: PluginTask -> task.plugin.accept(project) }) { task: PluginTask -> task.plugin.accept(project) })
@ -122,109 +124,81 @@ public class TaskManager @Inject constructor(val args: Args,
return RunTargetResult(result, messages) return RunTargetResult(result, messages)
} }
/**
* Create a dynamic graph representing all the tasks that need to be run.
*/
@VisibleForTesting @VisibleForTesting
fun <T> createGraph(projectName: String, taskNames: List<String>, dependencies: Multimap<String, T>, fun <T> createGraph(projectName: String, taskNames: List<String>, nodeMap: Multimap<String, T>,
dependsOn: TreeMultimap<String, String>,
reverseDependsOn: TreeMultimap<String, String>,
runBefore: TreeMultimap<String, String>, runBefore: TreeMultimap<String, String>,
runAfter: TreeMultimap<String, String>, runAfter: TreeMultimap<String, String>,
alwaysRunAfter: TreeMultimap<String, String>,
toName: (T) -> String, toName: (T) -> String,
accept: (T) -> Boolean): accept: (T) -> Boolean):
DynamicGraph<T> { DynamicGraph<T> {
val graph = DynamicGraph<T>()
val result = DynamicGraph<T>()
taskNames.forEach { taskName -> taskNames.forEach { taskName ->
val ti = TaskInfo(taskName) val ti = TaskInfo(taskName)
if (!dependencies.keys().contains(ti.taskName)) { if (!nodeMap.keys().contains(ti.taskName)) {
throw KobaltException("Unknown task: $taskName") throw KobaltException("Unknown task: $taskName")
} }
if (ti.matches(projectName)) { if (ti.matches(projectName)) {
dependencies[ti.taskName].forEach { task -> nodeMap[ti.taskName].forEach { task ->
if (task != null && accept(task)) { if (task != null && accept(task)) {
val reverseAfter = hashMapOf<String, String>() val toProcess = arrayListOf(task)
alwaysRunAfter.keys().forEach { from -> val seen = hashSetOf<String>()
val tasks = alwaysRunAfter.get(from) val newToProcess = arrayListOf<T>()
tasks.forEach { while (toProcess.size > 0) {
reverseAfter.put(it, from) toProcess.forEach { current ->
} result.addNode(current)
} seen.add(toName(current))
// fun maybeAddEdge(taskName: String, mm: Multimap<String, String>, isDependency: Boolean,
// If the current target is free, add it as a single node to the graph reverseEdges: Boolean = false) {
// mm[taskName]?.forEach {
val allFreeTasks = calculateFreeTasks(dependencies, reverseAfter) val addEdge = isDependency || (!isDependency && taskNames.contains(it))
val currentFreeTask = allFreeTasks.filter { log(3, " addEdge: $addEdge $taskName")
TaskInfo(projectName, toName(it)).taskName == toName(task) if (addEdge) {
} nodeMap[it].forEach { to ->
if (currentFreeTask.size == 1) { if (reverseEdges) {
currentFreeTask[0].let { log(3, " Adding reverse edge $to -> $task")
graph.addNode(it) result.addEdge(to, task)
} } else {
} log(3, " Adding edge $task -> $to")
result.addEdge(task, to)
// }
// Add the transitive closure of the current task as edges to the graph if (!seen.contains(it)) newToProcess.add(to)
//
val transitiveClosure = calculateTransitiveClosure(projectName, dependencies, ti)
transitiveClosure.forEach { pluginTask ->
val rb = runBefore.get(toName(pluginTask))
rb.forEach {
val tos = dependencies[it]
if (tos != null && tos.size > 0) {
tos.forEach { to ->
graph.addEdge(pluginTask, to)
}
} else {
log(2, "Couldn't find node $it: not applicable to project $projectName")
}
}
}
//
// runAfter nodes are run only if they are explicitly requested
//
arrayListOf<T>().let { allNodes ->
allNodes.addAll(graph.values)
allNodes.forEach { node ->
val nodeName = toName(node)
if (taskNames.contains(nodeName)) {
val ra = runAfter[nodeName]
ra?.forEach { o ->
dependencies[o]?.forEach {
if (taskNames.contains(toName(it))) {
graph.addEdge(node, it)
} }
seen.add(it)
} }
} }
} }
maybeAddEdge(ti.taskName, dependsOn, true, false)
maybeAddEdge(ti.taskName, reverseDependsOn, true, true)
maybeAddEdge(ti.taskName, runBefore, false, false)
maybeAddEdge(ti.taskName, runAfter, false, false)
} }
} toProcess.clear()
toProcess.addAll(newToProcess)
// newToProcess.clear()
// If any of the nodes in the graph has an "alwaysRunAfter", add that edge too
//
arrayListOf<T>().let { allNodes ->
allNodes.addAll(graph.values)
allNodes.forEach { node ->
val ra = alwaysRunAfter[toName(node)]
ra?.forEach { o ->
dependencies[o]?.forEach {
graph.addEdge(it, node)
}
}
}
} }
} }
} }
} else {
log(3, "Task $taskName does not match the current project $projectName, skipping it")
} }
} }
println("@@@ " + graph.dump()) return result
return graph
} }
/** /**
* Find the free tasks of the graph. * Find the free tasks of the graph.
*/ */
private fun <T> calculateFreeTasks(tasksByNames: Multimap<String, T>, reverseAfter: HashMap<String, String>) private fun <T> calculateFreeTasks(tasksByNames: Multimap<String, T>, runBefore: TreeMultimap<String, String>,
reverseAfter: HashMap<String,
String>)
: Collection<T> { : Collection<T> {
val freeTaskMap = hashMapOf<String, T>() val freeTaskMap = hashMapOf<String, T>()
tasksByNames.keys().forEach { tasksByNames.keys().forEach {
@ -238,49 +212,6 @@ public class TaskManager @Inject constructor(val args: Args,
return freeTaskMap.values return freeTaskMap.values
} }
/**
* Find the transitive closure for the given TaskInfo
*/
private fun <T> calculateTransitiveClosure(projectName: String, tasksByNames: Multimap<String, T>, ti: TaskInfo):
HashSet<T> {
log(3, "Processing ${ti.taskName}")
val transitiveClosure = hashSetOf<T>()
val seen = hashSetOf(ti.taskName)
val toProcess = hashSetOf(ti)
var done = false
while (! done) {
val newToProcess = hashSetOf<TaskInfo>()
log(3, "toProcess size: " + toProcess.size)
toProcess.forEach { target ->
val currentTask = TaskInfo(projectName, target.taskName)
val thisTask = tasksByNames[currentTask.taskName]
if (thisTask != null) {
transitiveClosure.addAll(thisTask)
val dependencyNames = runBefore.get(currentTask.taskName)
dependencyNames.forEach { dependencyName ->
if (!seen.contains(dependencyName)) {
newToProcess.add(currentTask)
seen.add(dependencyName)
}
}
dependencyNames.forEach {
newToProcess.add(TaskInfo(projectName, it))
}
} else {
log(1, "Couldn't find task ${currentTask.taskName}: not applicable to project $projectName")
}
}
done = newToProcess.isEmpty()
toProcess.clear()
toProcess.addAll(newToProcess)
}
return transitiveClosure
}
///// /////
// Manage the tasks // Manage the tasks
// //
@ -290,14 +221,16 @@ public class TaskManager @Inject constructor(val args: Args,
private val taskAnnotations = arrayListOf<TaskAnnotation>() private val taskAnnotations = arrayListOf<TaskAnnotation>()
class TaskAnnotation(val method: Method, val plugin: IPlugin, val name: String, val description: String, class TaskAnnotation(val method: Method, val plugin: IPlugin, val name: String, val description: String,
val runBefore: Array<String>, val runAfter: Array<String>, val alwaysRunAfter: Array<String>, val dependsOn: Array<String>, val reverseDependsOn: Array<String>,
val runBefore: Array<String>, val runAfter: Array<String>,
val callable: (Project) -> TaskResult) val callable: (Project) -> TaskResult)
/** /**
* Invoking a @Task means simply calling the method and returning its returned TaskResult. * Invoking a @Task means simply calling the method and returning its returned TaskResult.
*/ */
fun toTaskAnnotation(method: Method, plugin: IPlugin, ta: Task) fun toTaskAnnotation(method: Method, plugin: IPlugin, ta: Task)
= TaskAnnotation(method, plugin, ta.name, ta.description, ta.runBefore, ta.runAfter, ta.alwaysRunAfter, = TaskAnnotation(method, plugin, ta.name, ta.description, ta.dependsOn, ta.reverseDependsOn,
ta.runBefore, ta.runAfter,
{ project -> { project ->
method.invoke(plugin, project) as TaskResult method.invoke(plugin, project) as TaskResult
}) })
@ -307,7 +240,8 @@ public class TaskManager @Inject constructor(val args: Args,
* of the returned IncrementalTaskInfo. * of the returned IncrementalTaskInfo.
*/ */
fun toTaskAnnotation(method: Method, plugin: IPlugin, ta: IncrementalTask) fun toTaskAnnotation(method: Method, plugin: IPlugin, ta: IncrementalTask)
= TaskAnnotation(method, plugin, ta.name, ta.description, ta.runBefore, ta.runAfter, ta.alwaysRunAfter, = TaskAnnotation(method, plugin, ta.name, ta.description, ta.dependsOn, ta.reverseDependsOn,
ta.runBefore, ta.runAfter,
incrementalManagerFactory.create().toIncrementalTaskClosure(ta.name, { project -> incrementalManagerFactory.create().toIncrementalTaskClosure(ta.name, { project ->
method.invoke(plugin, project) as IncrementalTaskInfo method.invoke(plugin, project) as IncrementalTaskInfo
})) }))
@ -338,8 +272,9 @@ public class TaskManager @Inject constructor(val args: Args,
dynamicTasks.forEach { dynamicTask -> dynamicTasks.forEach { dynamicTask ->
val task = dynamicTask.task val task = dynamicTask.task
projects.filter { dynamicTask.plugin.accept(it) }.forEach { project -> projects.filter { dynamicTask.plugin.accept(it) }.forEach { project ->
addTask(dynamicTask.plugin, project, task.name, task.description, task.runBefore, task.runAfter, addTask(dynamicTask.plugin, project, task.name, task.description,
task.alwaysRunAfter, task.closure) task.dependsOn, task.reverseDependsOn, task.runBefore, task.runAfter,
task.closure)
} }
} }
} }
@ -360,14 +295,17 @@ public class TaskManager @Inject constructor(val args: Args,
private fun addAnnotationTask(plugin: IPlugin, project: Project, annotation: TaskAnnotation, private fun addAnnotationTask(plugin: IPlugin, project: Project, annotation: TaskAnnotation,
task: (Project) -> TaskResult) { task: (Project) -> TaskResult) {
addTask(plugin, project, annotation.name, annotation.description, annotation.runBefore.toList(), addTask(plugin, project, annotation.name, annotation.description,
annotation.runAfter.toList(), annotation.alwaysRunAfter.toList(), task) annotation.dependsOn.toList(), annotation.reverseDependsOn.toList(),
annotation.runBefore.toList(), annotation.runAfter.toList(),
task)
} }
fun addTask(plugin: IPlugin, project: Project, name: String, description: String = "", fun addTask(plugin: IPlugin, project: Project, name: String, description: String = "",
dependsOn: List<String> = listOf<String>(),
reverseDependsOn: List<String> = listOf<String>(),
runBefore: List<String> = listOf<String>(), runBefore: List<String> = listOf<String>(),
runAfter: List<String> = listOf<String>(), runAfter: List<String> = listOf<String>(),
alwaysRunAfter: List<String> = listOf<String>(),
task: (Project) -> TaskResult) { task: (Project) -> TaskResult) {
annotationTasks.add( annotationTasks.add(
object : BasePluginTask(plugin, name, description, project) { object : BasePluginTask(plugin, name, description, project) {
@ -376,9 +314,10 @@ public class TaskManager @Inject constructor(val args: Args,
return TaskResult2(taskResult.success, taskResult.errorMessage, this) return TaskResult2(taskResult.success, taskResult.errorMessage, this)
} }
}) })
dependsOn.forEach { dependsOn(it, name) }
reverseDependsOn.forEach { reverseDependsOn(it, name) }
runBefore.forEach { runBefore(it, name) } runBefore.forEach { runBefore(it, name) }
runAfter.forEach { runAfter(it, name) } runAfter.forEach { runAfter(it, name) }
alwaysRunAfter.forEach { alwaysRunAfter(it, name)}
} }
// //

View file

@ -52,7 +52,7 @@ class ApplicationPlugin @Inject constructor(val configActor: ConfigActor<Applica
runTask = { taskRun(project) }) runTask = { taskRun(project) })
} }
@Task(name = "run", description = "Run the main class", runAfter = arrayOf("install")) @Task(name = "run", description = "Run the main class", dependsOn = arrayOf("install"))
fun taskRun(project: Project): TaskResult { fun taskRun(project: Project): TaskResult {
val runContributor = ActorUtils.selectAffinityActor(project, context, val runContributor = ActorUtils.selectAffinityActor(project, context,
context.pluginInfo.runnerContributors) context.pluginInfo.runnerContributors)

View file

@ -79,7 +79,7 @@ class PackagingPlugin @Inject constructor(val dependencyManager : DependencyMana
} }
@Task(name = TASK_ASSEMBLE, description = "Package the artifacts", @Task(name = TASK_ASSEMBLE, description = "Package the artifacts",
runAfter = arrayOf(JvmCompilerPlugin.TASK_COMPILE)) dependsOn = arrayOf(JvmCompilerPlugin.TASK_COMPILE))
fun doTaskAssemble(project: Project) : TaskResult { fun doTaskAssemble(project: Project) : TaskResult {
// Incremental assembly contributors // Incremental assembly contributors
context.pluginInfo.incrementalAssemblyContributors.forEach { context.pluginInfo.incrementalAssemblyContributors.forEach {
@ -131,7 +131,7 @@ class PackagingPlugin @Inject constructor(val dependencyManager : DependencyMana
@Task(name = PackagingPlugin.TASK_INSTALL, description = "Install the artifacts", @Task(name = PackagingPlugin.TASK_INSTALL, description = "Install the artifacts",
runAfter = arrayOf(PackagingPlugin.TASK_ASSEMBLE)) dependsOn = arrayOf(PackagingPlugin.TASK_ASSEMBLE))
fun taskInstall(project: Project) : TaskResult { fun taskInstall(project: Project) : TaskResult {
val config = configurationFor(project) ?: InstallConfig() val config = configurationFor(project) ?: InstallConfig()
val buildDir = project.projectProperties.getString(LIBS_DIR) val buildDir = project.projectProperties.getString(LIBS_DIR)

View file

@ -33,7 +33,7 @@ public class PublishPlugin @Inject constructor(val files: KFiles, val factory: P
} }
@Suppress("UNUSED_FUNCTION_LITERAL") @Suppress("UNUSED_FUNCTION_LITERAL")
@Task(name = TASK_GENERATE_POM, description = "Generate the .pom file", runAfter = arrayOf("assemble")) @Task(name = TASK_GENERATE_POM, description = "Generate the .pom file", dependsOn = arrayOf("assemble"))
fun taskGeneratePom(project: Project): TaskResult { fun taskGeneratePom(project: Project): TaskResult {
factory.create(project).generate() factory.create(project).generate()
return TaskResult() return TaskResult()
@ -56,7 +56,7 @@ public class PublishPlugin @Inject constructor(val files: KFiles, val factory: P
} }
@Task(name = TASK_UPLOAD_BINTRAY, description = "Upload files to Bintray", @Task(name = TASK_UPLOAD_BINTRAY, description = "Upload files to Bintray",
runAfter = arrayOf(TASK_GENERATE_POM)) dependsOn = arrayOf(TASK_GENERATE_POM))
fun taskUploadBintray(project: Project): TaskResult { fun taskUploadBintray(project: Project): TaskResult {
validateProject(project) validateProject(project)
return uploadBintray(project) return uploadBintray(project)
@ -100,7 +100,7 @@ public class PublishPlugin @Inject constructor(val files: KFiles, val factory: P
} }
@Task(name = TASK_UPLOAD_GITHUB, description = "Upload files to Github", @Task(name = TASK_UPLOAD_GITHUB, description = "Upload files to Github",
runAfter = arrayOf(TASK_GENERATE_POM)) dependsOn = arrayOf(TASK_GENERATE_POM))
fun taskUploadGithub(project: Project): TaskResult { fun taskUploadGithub(project: Project): TaskResult {
validateProject(project) validateProject(project)
return uploadGithub(project) return uploadGithub(project)

View file

@ -31,22 +31,24 @@ class TaskManagerTest @Inject constructor(val taskManager: TaskManager) {
} }
private fun runTasks(tasks: List<String>) : List<String> { private fun runTasks(tasks: List<String>) : List<String> {
val runBefore = TreeMultimap.create<String, String>().apply { val dependsOn = TreeMultimap.create<String, String>().apply {
put("assemble", "compile") put("assemble", "compile")
} }
val reverseDependsOn = TreeMultimap.create<String, String>().apply {
put("clean", "copyVersion")
put("compile", "postCompile")
}
val runBefore = TreeMultimap.create<String, String>().apply {
}
val runAfter = TreeMultimap.create<String, String>().apply { val runAfter = TreeMultimap.create<String, String>().apply {
put("compile", "clean") put("compile", "clean")
put("postCompile", "compile")
}
val alwaysRunAfter = TreeMultimap.create<String, String>().apply {
put("clean", "copyVersion")
} }
val dependencies = TreeMultimap.create<String, String>().apply { val dependencies = TreeMultimap.create<String, String>().apply {
listOf("assemble", "compile", "clean", "copyVersion", "postCompile").forEach { listOf("assemble", "compile", "clean", "copyVersion", "postCompile").forEach {
put(it, it) put(it, it)
} }
} }
val graph = taskManager.createGraph("", tasks, dependencies, runBefore, runAfter, alwaysRunAfter, val graph = taskManager.createGraph("", tasks, dependencies, dependsOn, reverseDependsOn, runBefore, runAfter,
{ it }, { t -> true }) { it }, { t -> true })
val result = DryRunGraphExecutor(graph).run() val result = DryRunGraphExecutor(graph).run()
return result return result
@ -55,11 +57,12 @@ class TaskManagerTest @Inject constructor(val taskManager: TaskManager) {
@Test @Test
fun graphTest() { fun graphTest() {
KobaltLogger.LOG_LEVEL = 3 KobaltLogger.LOG_LEVEL = 3
Assert.assertEquals(runTasks(listOf("compile")), listOf("compile", "postCompile"))
Assert.assertEquals(runTasks(listOf("postCompile")), listOf("postCompile")) Assert.assertEquals(runTasks(listOf("postCompile")), listOf("postCompile"))
Assert.assertEquals(runTasks(listOf("compile")), listOf("compile"))
Assert.assertEquals(runTasks(listOf("compile", "postCompile")), listOf("compile", "postCompile")) Assert.assertEquals(runTasks(listOf("compile", "postCompile")), listOf("compile", "postCompile"))
Assert.assertEquals(runTasks(listOf("clean")), listOf("clean", "copyVersion")) Assert.assertEquals(runTasks(listOf("clean")), listOf("clean", "copyVersion"))
Assert.assertEquals(runTasks(listOf("clean", "compile")), listOf("clean", "compile", "copyVersion")) Assert.assertEquals(runTasks(listOf("clean", "compile")), listOf("clean", "compile", "copyVersion",
"postCompile"))
Assert.assertEquals(runTasks(listOf("assemble")), listOf("compile", "assemble")) Assert.assertEquals(runTasks(listOf("assemble")), listOf("compile", "assemble"))
Assert.assertEquals(runTasks(listOf("clean", "assemble")), listOf("clean", "compile", "assemble", Assert.assertEquals(runTasks(listOf("clean", "assemble")), listOf("clean", "compile", "assemble",
"copyVersion")) "copyVersion"))