first functional version
This commit is contained in:
22
LICENSE.md
Normal file
22
LICENSE.md
Normal file
@@ -0,0 +1,22 @@
|
||||
Copyright 2020 Walter Oggioni
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
@@ -1,14 +1,15 @@
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenLocal()
|
||||
}
|
||||
|
||||
group = "net.corda"
|
||||
group = "net.woggioni.plugins"
|
||||
version = 0.1
|
||||
|
||||
plugins {
|
||||
`java-gradle-plugin`
|
||||
`maven-publish`
|
||||
id("org.jetbrains.kotlin.jvm") version("1.3.61")
|
||||
id("org.jetbrains.kotlin.jvm") version("1.3.71")
|
||||
id("com.gradle.plugin-publish") version("0.10.1")
|
||||
}
|
||||
|
||||
@@ -26,6 +27,7 @@ dependencies {
|
||||
|
||||
// Use the Kotlin JDK 8 standard library.
|
||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
||||
implementation("net.woggioni:worth:1.0")
|
||||
|
||||
// Use the Kotlin test library.
|
||||
// testImplementation("org.jetbrains.kotlin:kotlin-test")
|
||||
@@ -41,8 +43,8 @@ dependencies {
|
||||
gradlePlugin {
|
||||
// Define the plugin
|
||||
val my_first_plugin by plugins.creating {
|
||||
id = "net.corda.my-first-plugin"
|
||||
implementationClass = "my.first.plugin.MyFirstPluginPlugin"
|
||||
id = "net.woggioni.plugins.dependency-export"
|
||||
implementationClass = "net.woggioni.plugins.DependencyExportPlugin"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,3 +77,7 @@ tasks.withType<Wrapper>().configureEach {
|
||||
gradleVersion = "6.1.1"
|
||||
distributionType = Wrapper.DistributionType.ALL
|
||||
}
|
||||
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
|
||||
kotlinOptions.jvmTarget = "1.8"
|
||||
}
|
@@ -7,4 +7,4 @@
|
||||
* in the user manual at https://docs.gradle.org/6.1.1/userguide/multi_project_builds.html
|
||||
*/
|
||||
|
||||
rootProject.name = "my-first-plugin"
|
||||
rootProject.name = "dependency-export"
|
||||
|
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* This Kotlin source file was generated by the Gradle 'init' task.
|
||||
*/
|
||||
package my.first.plugin
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Plugin
|
||||
|
||||
|
||||
///**
|
||||
// * A simple 'hello world' plugin.
|
||||
// */
|
||||
//class MyFirstPluginPlugin: Plugin<Project> {
|
||||
// override fun apply(project: Project) {
|
||||
// // Register a task
|
||||
// project.tasks.register("greeting") { task ->
|
||||
// task.doLast {
|
||||
// println("Hello from plugin 'my.first.plugin.greeting'")
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
open class MyFirstPluginPluginExtension {
|
||||
var message: String? = null
|
||||
var greeter: String? = null
|
||||
}
|
||||
|
||||
class MyFirstPluginPlugin : Plugin<Project> {
|
||||
override fun apply(project: Project) {
|
||||
val extension = MyFirstPluginPluginExtension()
|
||||
project.extensions.add(MyFirstPluginPluginExtension::class.java, "my_first_plugin", MyFirstPluginPluginExtension())
|
||||
project.tasks.register("hello") {
|
||||
it.doLast {
|
||||
println("${extension.message} from ${extension.greeter}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
173
src/main/kotlin/net/woggioni/plugins/DependencyExportPlugin.kt
Normal file
173
src/main/kotlin/net/woggioni/plugins/DependencyExportPlugin.kt
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* This Kotlin source file was generated by the Gradle 'init' task.
|
||||
*/
|
||||
package net.woggioni.plugins
|
||||
|
||||
import net.woggioni.jwo.JWO
|
||||
import net.woggioni.jwo.tree.StackContext
|
||||
import net.woggioni.jwo.tree.TreeNode
|
||||
import net.woggioni.jwo.tree.TreeNodeVisitor
|
||||
import net.woggioni.jwo.tree.TreeWalker
|
||||
import net.woggioni.worth.serialization.json.JSONDumper
|
||||
import net.woggioni.worth.value.ObjectValue
|
||||
import net.woggioni.worth.xface.Value
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.component.ModuleComponentIdentifier
|
||||
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
|
||||
import org.gradle.api.artifacts.result.ResolvedComponentResult
|
||||
import org.gradle.api.artifacts.result.ResolvedDependencyResult
|
||||
import org.gradle.api.artifacts.result.UnresolvedDependencyResult
|
||||
import java.io.BufferedWriter
|
||||
import java.io.OutputStreamWriter
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
|
||||
open class DependencyExportPluginExtension {
|
||||
var configurationName: String = "default"
|
||||
}
|
||||
|
||||
object DependencyExporter {
|
||||
|
||||
fun graphviz(project: Project, configurationName : String) {
|
||||
var sequence = 0
|
||||
val map = HashMap<ResolvedComponentResult, Int>()
|
||||
val resolutionResult = project.configurations.single {
|
||||
it.name == configurationName
|
||||
}.incoming.resolutionResult
|
||||
project.buildDir.toPath().let {
|
||||
Files.createDirectories(it)
|
||||
}.let {
|
||||
BufferedWriter(
|
||||
OutputStreamWriter(
|
||||
Files.newOutputStream(project.buildDir.toPath().resolve("dependencies.dot"))))
|
||||
}.use { writer ->
|
||||
writer.write("digraph G {")
|
||||
writer.newLine()
|
||||
writer.write(" #rankdir=\"LR\";")
|
||||
writer.newLine()
|
||||
for (component in resolutionResult.allComponents) {
|
||||
map.computeIfAbsent(component) {
|
||||
sequence++
|
||||
}
|
||||
val (shape, color) = when (component.id) {
|
||||
is ProjectComponentIdentifier -> "box" to "#88ff88"
|
||||
is ModuleComponentIdentifier -> "oval" to "#ffff88"
|
||||
else -> throw NotImplementedError("${component.id::class}")
|
||||
}
|
||||
val attrs = mapOf(
|
||||
"label" to component.id.displayName,
|
||||
"shape" to shape,
|
||||
"style" to "filled",
|
||||
"fillcolor" to color
|
||||
)
|
||||
writer.write(" node_${map[component]} [" +
|
||||
attrs.entries
|
||||
.asSequence()
|
||||
.map { "${it.key}=\"${it.value}\"" }.joinToString(", ") +
|
||||
"];")
|
||||
writer.newLine()
|
||||
}
|
||||
|
||||
for (component in resolutionResult.allComponents) {
|
||||
|
||||
component.dependencies.map { dependency ->
|
||||
when (dependency) {
|
||||
is ResolvedDependencyResult -> dependency
|
||||
is UnresolvedDependencyResult -> {
|
||||
throw dependency.failure
|
||||
}
|
||||
else -> {
|
||||
throw NotImplementedError("${dependency::class}")
|
||||
}
|
||||
}
|
||||
}.map(ResolvedDependencyResult::getSelected).forEach { child ->
|
||||
writer.write(" node_${map[component]} -> node_${map[child]};")
|
||||
writer.newLine()
|
||||
}
|
||||
}
|
||||
writer.write("}")
|
||||
writer.newLine()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DependencyTreeNode(val component: ResolvedComponentResult) : TreeNode<DependencyTreeNode> {
|
||||
override fun children(): Iterator<DependencyTreeNode> {
|
||||
return object : Iterator<DependencyTreeNode> {
|
||||
val it = component.dependencies.iterator()
|
||||
override fun hasNext(): Boolean {
|
||||
return it.hasNext()
|
||||
}
|
||||
|
||||
override fun next(): DependencyTreeNode {
|
||||
val dependency = it.next()
|
||||
return when (dependency) {
|
||||
is ResolvedDependencyResult -> {
|
||||
DependencyTreeNode(dependency.selected)
|
||||
}
|
||||
is UnresolvedDependencyResult -> {
|
||||
throw dependency.failure
|
||||
}
|
||||
else -> {
|
||||
throw NotImplementedError("${dependency::class}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun export(project: Project) {
|
||||
val cfg = Value.Configuration.builder()
|
||||
.serializeReferences(true)
|
||||
.objectValueImplementation(ObjectValue.Implementation.ArrayList)
|
||||
.build()
|
||||
val result = ObjectValue.newInstance(cfg)
|
||||
project.configurations.all { configuration ->
|
||||
if (configuration.isCanBeResolved) {
|
||||
val configDeps = ObjectValue.newInstance(cfg)
|
||||
val visitor = object : TreeNodeVisitor<DependencyTreeNode, ObjectValue> {
|
||||
override fun visitPre(stack: MutableList<StackContext<DependencyTreeNode, ObjectValue>>): TreeNodeVisitor.VisitOutcome {
|
||||
val stackElement = JWO.tail(stack)
|
||||
stackElement.context = ObjectValue.newInstance(cfg)
|
||||
val id = stackElement.node.component.id
|
||||
if (stack.size == 1) {
|
||||
configDeps.put(id.displayName, stackElement.context)
|
||||
} else if (stack.size > 1) {
|
||||
val parentStackElement = JWO.tail(stack, -2)
|
||||
parentStackElement.context.put(id.displayName, stackElement.context)
|
||||
}
|
||||
return TreeNodeVisitor.VisitOutcome.CONTINUE
|
||||
}
|
||||
// override fun visitPost(stack: MutableList<StackContext<DependencyTreeNode, ObjectValue>>?) {
|
||||
// val stackElement = JWO.tail(stack)
|
||||
// if(stack.size > 1) {
|
||||
// val parentStackElement = JWO.tail(stack, -2)
|
||||
// parentStackElement.context.add(StringValue(stackElement.node.component.toString()))
|
||||
// }
|
||||
// }
|
||||
}
|
||||
TreeWalker(visitor).walk(DependencyTreeNode(configuration.incoming.resolutionResult.root))
|
||||
result.put(configuration.name, configDeps)
|
||||
}
|
||||
}
|
||||
BufferedWriter(OutputStreamWriter(Files.newOutputStream(Paths.get("/tmp/dependencies.json")))).use {
|
||||
JSONDumper.newInstance(cfg).dump(result, it)
|
||||
}
|
||||
}
|
||||
|
||||
class DependencyExportPlugin : Plugin<Project> {
|
||||
override fun apply(project: Project) {
|
||||
val extension = DependencyExportPluginExtension()
|
||||
project.extensions.add(DependencyExportPluginExtension::class.java, "exportDependencies", extension)
|
||||
project.tasks.register("exportDependencies") {
|
||||
it.doLast {
|
||||
val propertyKey = "exportDependencies.configurationName"
|
||||
val properties = project.properties
|
||||
val configurationName = properties.getOrDefault(propertyKey, extension.configurationName) as String
|
||||
DependencyExporter.graphviz(project, configurationName = configurationName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package my.first.plugin
|
||||
package net.woggioni.plugins
|
||||
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.IOException
|
@@ -1,23 +1,17 @@
|
||||
/*
|
||||
* This Kotlin source file was generated by the Gradle 'init' task.
|
||||
*/
|
||||
package my.first.plugin.test
|
||||
package net.woggioni.plugins
|
||||
|
||||
import my.first.plugin.installResource
|
||||
import org.gradle.testfixtures.ProjectBuilder
|
||||
import net.woggioni.plugins.installResource
|
||||
import org.gradle.testkit.runner.GradleRunner
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.io.TempDir
|
||||
import java.io.File
|
||||
import java.net.URLClassLoader
|
||||
import java.nio.file.Path
|
||||
|
||||
|
||||
/**
|
||||
* A simple unit test for the 'my.first.plugin.greeting' plugin.
|
||||
*/
|
||||
class MyFirstPluginPluginTest {
|
||||
class DependencyExportPluginTest {
|
||||
|
||||
@TempDir
|
||||
lateinit var testProjectDir : Path
|
||||
@@ -37,33 +31,20 @@ class MyFirstPluginPluginTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun fooKotlin() {
|
||||
fun testKotlin() {
|
||||
installResource("build.gradle.kts", testProjectDir)
|
||||
installResource("settings.gradle.kts", testProjectDir)
|
||||
installResource("gradle.properties", testProjectDir)
|
||||
val runner = getStandardGradleRunnerFor("hello")
|
||||
val runner = getStandardGradleRunnerFor("exportDependencies")
|
||||
val result = runner.build()
|
||||
println(result.output)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun fooGroovy() {
|
||||
fun testGroovy() {
|
||||
installResource("build.gradle", testProjectDir)
|
||||
installResource("settings.gradle.kts", testProjectDir)
|
||||
installResource("gradle.properties", testProjectDir)
|
||||
val runner = getStandardGradleRunnerFor("hello")
|
||||
val runner = getStandardGradleRunnerFor("exportDependencies")
|
||||
val result = runner.build()
|
||||
println(result.output)
|
||||
}
|
||||
|
||||
// @Test
|
||||
// fun `plugin registers task`() {
|
||||
// // Create a test project and apply the plugin
|
||||
// val project = ProjectBuilder.builder().build()
|
||||
// project.plugins.apply("my.first.plugin.MyFirstPlugin")
|
||||
//
|
||||
// // Verify the result
|
||||
// val task = project.tasks.findByName("hello")!!
|
||||
// println(task.outputs.hasOutput)
|
||||
// }
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
plugins {
|
||||
id "net.corda.my-first-plugin"
|
||||
}
|
||||
|
||||
my_first_plugin {
|
||||
message = 'Hi'
|
||||
greeter = 'Gradle'
|
||||
}
|
@@ -1,21 +0,0 @@
|
||||
//buildscript {
|
||||
// repositories {
|
||||
// mavenLocal()
|
||||
// jcenter()
|
||||
// mavenCentral()
|
||||
// }
|
||||
// dependencies {
|
||||
// classpath("net.corda:my-first-plugin:0.1")
|
||||
// }
|
||||
//}
|
||||
|
||||
plugins {
|
||||
id("net.corda.my-first-plugin")
|
||||
}
|
||||
//apply(plugin = "net.corda.my-first-plugin")
|
||||
import my.first.plugin.MyFirstPluginPluginExtension
|
||||
|
||||
configure<my.first.plugin.MyFirstPluginPluginExtension> {
|
||||
message = "Hi"
|
||||
greeter = "Gradle"
|
||||
}
|
17
src/test/resources/net/woggioni/plugins/build.gradle
Normal file
17
src/test/resources/net/woggioni/plugins/build.gradle
Normal file
@@ -0,0 +1,17 @@
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.jvm" version "1.3.61"
|
||||
id "net.woggioni.plugins.dependency-export"
|
||||
}
|
||||
|
||||
exportDependencies {
|
||||
configurationName = 'runtime'
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenLocal()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
runtime("org.hibernate:hibernate-core:5.4.13.Final")
|
||||
}
|
14
src/test/resources/net/woggioni/plugins/build.gradle.kts
Normal file
14
src/test/resources/net/woggioni/plugins/build.gradle.kts
Normal file
@@ -0,0 +1,14 @@
|
||||
plugins {
|
||||
kotlin("jvm") version "1.3.71"
|
||||
id("net.woggioni.plugins.dependency-export")
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenLocal()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
runtime("org.hibernate:hibernate-core:5.4.13.Final")
|
||||
}
|
||||
|
Reference in New Issue
Block a user