From 2ff8c958c1a3a9a2f1bfb6c17154ec840ac5fbc0 Mon Sep 17 00:00:00 2001 From: Walter Oggioni Date: Mon, 8 Feb 2021 14:19:53 +0100 Subject: [PATCH] refactor of dependency-export plugin to allow for cli argument configuration --- build.gradle | 30 +++ build.gradle.kts | 26 --- dependency-export/README.md | 47 ++-- dependency-export/build.gradle.kts | 23 +- dependency-export/sample/groovy/build.gradle | 8 +- .../sample/kotlin/build.gradle.kts | 8 +- .../export/DependencyExportPlugin.java | 32 +++ .../dependency/export/ExportDependencies.java | 204 ++++++++++++++++ .../dependency/export/RenderDependencies.java | 87 +++++++ .../export/DependencyExportPlugin.kt | 220 ------------------ .../export/DependencyExportPluginTest.java | 93 ++++++++ .../export/DependencyExportPluginTest.kt | 52 ----- .../plugins/dependency/export/Powerup.kt | 33 --- .../gradle/dependency/export/build.gradle | 18 ++ .../gradle/dependency/export/build.gradle.kts | 17 ++ .../plugins/dependency/export/build.gradle | 17 -- .../dependency/export/build.gradle.kts | 14 -- gradle.properties | 4 + gradle/wrapper/gradle-wrapper.jar | Bin 58910 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- gradlew.bat | 21 +- settings.gradle | 15 ++ settings.gradle.kts | 11 - 24 files changed, 537 insertions(+), 447 deletions(-) create mode 100644 build.gradle delete mode 100644 build.gradle.kts create mode 100644 dependency-export/src/main/java/net/woggioni/gradle/dependency/export/DependencyExportPlugin.java create mode 100644 dependency-export/src/main/java/net/woggioni/gradle/dependency/export/ExportDependencies.java create mode 100644 dependency-export/src/main/java/net/woggioni/gradle/dependency/export/RenderDependencies.java delete mode 100644 dependency-export/src/main/kotlin/net/woggioni/plugins/dependency/export/DependencyExportPlugin.kt create mode 100644 dependency-export/src/test/java/net/woggioni/gradle/dependency/export/DependencyExportPluginTest.java delete mode 100644 dependency-export/src/test/kotlin/net/woggioni/plugins/dependency/export/DependencyExportPluginTest.kt delete mode 100644 dependency-export/src/test/kotlin/net/woggioni/plugins/dependency/export/Powerup.kt create mode 100644 dependency-export/src/test/resources/net/woggioni/gradle/dependency/export/build.gradle create mode 100644 dependency-export/src/test/resources/net/woggioni/gradle/dependency/export/build.gradle.kts delete mode 100644 dependency-export/src/test/resources/net/woggioni/plugins/dependency/export/build.gradle delete mode 100644 dependency-export/src/test/resources/net/woggioni/plugins/dependency/export/build.gradle.kts create mode 100644 settings.gradle delete mode 100644 settings.gradle.kts diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..90b8cfe --- /dev/null +++ b/build.gradle @@ -0,0 +1,30 @@ +allprojects { + apply plugin: 'java-library' + repositories { + mavenLocal() + mavenCentral() + jcenter() + } + group = "net.woggioni.gradle" + version = 0.1 + + dependencies { + ['compileOnly', 'annotationProcessor', 'testCompileOnly', 'testAnnotationProcessor'].each { conf -> + add(conf, [group: "org.projectlombok", name: "lombok", version: project['version.lombok']]) + } + add("testImplementation", create(group: "org.junit.jupiter", name:"junit-jupiter-api", version: project["version.junitJupiter"])) + add("testRuntimeOnly", create(group: "org.junit.jupiter", name: "junit-jupiter-engine", version: project["version.junitJupiter"])) + add("testImplementation", gradleTestKit()) + } + + tasks.named("test", Test) { + useJUnitPlatform() + } +} + +wrapper { + gradleVersion = "6.8" + distributionType = Wrapper.DistributionType.ALL +} + + diff --git a/build.gradle.kts b/build.gradle.kts deleted file mode 100644 index 412c6b1..0000000 --- a/build.gradle.kts +++ /dev/null @@ -1,26 +0,0 @@ -allprojects { - apply() - repositories { - mavenLocal() - mavenCentral() - jcenter() - } - group = "net.woggioni.plugins" - version = 0.1 - - dependencies { - add("testImplementation", create(group="org.junit.jupiter", name="junit-jupiter-api", version=project["version.junitJupiter"])) - add("testRuntimeOnly", create(group="org.junit.jupiter", name="junit-jupiter-engine", version=project["version.junitJupiter"])) - add("testImplementation", gradleTestKit()) - } - - tasks.named("test") { - useJUnitPlatform() - } -} - -tasks.withType().configureEach { - gradleVersion = "6.7" - distributionType = Wrapper.DistributionType.ALL -} - diff --git a/dependency-export/README.md b/dependency-export/README.md index 32a061e..5515cfa 100644 --- a/dependency-export/README.md +++ b/dependency-export/README.md @@ -36,14 +36,12 @@ plugins { } ``` -You can also enable it globally on your machine just create a `~/.gradle/init.gradle` file with this content +You can also enable it globally on your machine, just create a `~/.gradle/init.gradle` file with this content ```groovy initscript { repositories { mavenLocal() - mavenCentral() - jcenter() } dependencies { classpath "net.woggioni.plugins:dependency-export:0.1" @@ -82,18 +80,15 @@ renderDependencies { and using Kotlin DSL ```kotlin -import net.woggioni.plugins.ExportDependenciesPluginExtension -import net.woggioni.plugins.RenderDependenciesPluginExtension - -configure { - configurationName = "default" - outputFile = "dependencies.dot" +tasks.named("exportDependencies") { + configurationName.set("compileClasspath") + outputFile.set(project.file("dependencies.dot")) } -configure { - format = "xlib" - outputFile = "renderedDependencies" - graphvizExecutable = "graphviz" +tasks.named("renderDependencies") { + format.set("xlib") + outputFile.set(project.file("renderedDependencies")) + graphvizExecutable.set("graphviz") } ``` @@ -102,24 +97,30 @@ or using its correspondent Gradle's [project properties](https://docs.gradle.org For example to override the output format of the `renderDependencies` task from the CLI: ```bash -gradle -PrenderDependencies.format=svg renderDependencies +gradle exportDependencies --configuration=compileClasspath renderDependencies --format=svg ``` ### Parameter description -- `exportDependencies.configurationName` will select the Gradle's configuration -(that word you put in the `dependencies` section of your build before `groupId:artifactId:versionId` tuple) - that will be represented in the graph -- `exportDependencies.outputFile` will specify the location of the generated `.dot` file -(note that if a relative path is provided, it will be interpreted as relative to the project's build directory) -- `renderDependencies.format` will specify the format of the file generated by Graphviz. +#### Attributes of task `net.woggioni.gradle.dependency.export.ExportDependencies` +- `configurationName` will select the Gradle's configuration + (that word you put in the `dependencies` section of your build before `groupId:artifactId:versionId` tuple) + that will be represented in the graph. It can also be specified from CLI using `--configuration`. +- `outputFile` will specify the location of the generated `.dot` file +(note that if a relative path is provided, it will be interpreted as relative to the project's build directory). + It can also be specified from CLI using `--output`. + +#### Attributes of task `net.woggioni.gradle.dependency.export.RenderDependencies` +- `format` will specify the format of the file generated by Graphviz. The default output format is `xlib` which, on a linux machine with a GUI, will open a window with an interactive (with zoom and pan) view of your dependencies (this is a special format that will not output any file). Otherwise you can choose between any other output format supported by Graphviz, refer to [its official documentation](https://graphviz.gitlab.io/_pages/doc/info/output.html) for more details. -- `renderDependencies.outputFile` will specify the location of the generated file (note that if a -relative path is provided, it will be interpreted as relative to the project's build directory) -- `renderDependencies.graphvizExecutable` will set the executable that will be launched to invoke + It can also be specified from CLI using `--format`. +- `outputFile` will specify the location of the generated file (note that if a +relative path is provided, it will be interpreted as relative to the project's build directory). + It can also be specified from CLI using `--output`. +- `graphvizExecutable` will set the executable that will be launched to invoke Graphviz so that, if you have it installed in an exotic location outside of your `PATH` or, for any reason, you renamed it in some way, you can configure it here. diff --git a/dependency-export/build.gradle.kts b/dependency-export/build.gradle.kts index cd79cdf..d696881 100644 --- a/dependency-export/build.gradle.kts +++ b/dependency-export/build.gradle.kts @@ -1,16 +1,10 @@ plugins { `java-gradle-plugin` `maven-publish` - id("org.jetbrains.kotlin.jvm") id("com.gradle.plugin-publish") } dependencies { - // Align versions of all Kotlin components - implementation(platform("org.jetbrains.kotlin:kotlin-bom")) - - // Use the Kotlin JDK 8 standard library. - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") } java { @@ -27,19 +21,8 @@ arrayOf("apiElements", "runtimeElements").forEach { name : String -> gradlePlugin { - plugins { - create("DependencyExportPlugin") { - id = "net.woggioni.plugins.dependency-export" - implementationClass = "net.woggioni.plugins.dependency.export.DependencyExportPlugin" - } + val dependencyExportPlugin by plugins.creating { + id = "net.woggioni.gradle.dependency-export" + implementationClass = "net.woggioni.gradle.dependency.export.DependencyExportPlugin" } } - -tasks.withType().configureEach { - kotlinOptions { - languageVersion = "1.3" - apiVersion = "1.3" - jvmTarget = "1.8" - javaParameters = true // Useful for reflection. - } -} \ No newline at end of file diff --git a/dependency-export/sample/groovy/build.gradle b/dependency-export/sample/groovy/build.gradle index b3a9d89..6f69a01 100644 --- a/dependency-export/sample/groovy/build.gradle +++ b/dependency-export/sample/groovy/build.gradle @@ -4,13 +4,12 @@ buildscript { } dependencies { - classpath "net.woggioni.plugins:dependency-export:0.1" + classpath "net.woggioni.gradle:dependency-export:0.1" } } plugins { - id "org.jetbrains.kotlin.jvm" version "1.3.61" - id "net.woggioni.plugins.dependency-export" version "0.1" + id "net.woggioni.gradle.dependency-export" version "0.1" } repositories { @@ -18,9 +17,8 @@ repositories { mavenLocal() } - exportDependencies { - configurationName = 'runtime' + configurationName = 'runtimeCl' } renderDependencies { diff --git a/dependency-export/sample/kotlin/build.gradle.kts b/dependency-export/sample/kotlin/build.gradle.kts index 64f3c71..55355a7 100644 --- a/dependency-export/sample/kotlin/build.gradle.kts +++ b/dependency-export/sample/kotlin/build.gradle.kts @@ -5,16 +5,12 @@ buildscript { mavenCentral() } dependencies { - classpath("net.woggioni.plugins:dependency-export:0.1") + classpath("net.woggioni.gradle:dependency-export:0.1") } } -import net.woggioni.plugins.ExportDependenciesPluginExtension -import net.woggioni.plugins.RenderDependenciesPluginExtension - plugins { - kotlin("jvm") version "1.3.71" - id("net.woggioni.plugins.dependency-export") version "0.1" + id("net.woggioni.gradle.dependency-export") version "0.1" } repositories { diff --git a/dependency-export/src/main/java/net/woggioni/gradle/dependency/export/DependencyExportPlugin.java b/dependency-export/src/main/java/net/woggioni/gradle/dependency/export/DependencyExportPlugin.java new file mode 100644 index 0000000..848ec75 --- /dev/null +++ b/dependency-export/src/main/java/net/woggioni/gradle/dependency/export/DependencyExportPlugin.java @@ -0,0 +1,32 @@ +package net.woggioni.gradle.dependency.export; + +import org.gradle.api.Action; +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.plugins.JavaBasePlugin; +import org.gradle.api.plugins.ObjectConfigurationAction; +import org.gradle.api.provider.Provider; + +public class DependencyExportPlugin implements Plugin { + @Override + public void apply(Project project) { + project.apply(new Action() { + @Override + public void execute(ObjectConfigurationAction objectConfigurationAction) { + objectConfigurationAction.plugin(JavaBasePlugin.class); + } + }); + Provider exportDependenciesTask = + project.getTasks().register("exportDependencies", ExportDependencies.class); + Provider renderDependenciesTask = + project.getTasks().register("renderDependencies", RenderDependencies.class, new Action() { + @Override + public void execute(RenderDependencies renderDependencies) { + renderDependencies.setExportTask(exportDependenciesTask); + } + }); + +// project.getExtensions().getExtraProperties().set(ExportDependencies.class.getSimpleName(), ExportDependencies.class); + project.getExtensions().getExtraProperties().set(RenderDependencies.class.getSimpleName(), RenderDependencies.class); + } +} diff --git a/dependency-export/src/main/java/net/woggioni/gradle/dependency/export/ExportDependencies.java b/dependency-export/src/main/java/net/woggioni/gradle/dependency/export/ExportDependencies.java new file mode 100644 index 0000000..f4acc4c --- /dev/null +++ b/dependency-export/src/main/java/net/woggioni/gradle/dependency/export/ExportDependencies.java @@ -0,0 +1,204 @@ +package net.woggioni.gradle.dependency.export; + +import lombok.*; +import org.gradle.api.DefaultTask; +import org.gradle.api.GradleException; +import org.gradle.api.artifacts.Configuration; +import org.gradle.api.artifacts.ResolvedArtifact; +import org.gradle.api.artifacts.component.ComponentIdentifier; +import org.gradle.api.artifacts.component.ModuleComponentIdentifier; +import org.gradle.api.artifacts.component.ProjectComponentIdentifier; +import org.gradle.api.artifacts.result.*; +import org.gradle.api.file.FileCollection; +import org.gradle.api.model.ObjectFactory; +import org.gradle.api.plugins.JavaPluginConvention; +import org.gradle.api.provider.Property; +import org.gradle.api.provider.Provider; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.InputFiles; +import org.gradle.api.tasks.OutputFile; +import org.gradle.api.tasks.TaskAction; +import org.gradle.api.tasks.options.Option; + +import javax.inject.Inject; +import java.io.File; +import java.io.Writer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; +import java.util.stream.Collector; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class ExportDependencies extends DefaultTask { + + @Getter + @Setter + @Input + private Property configurationName; + + @Getter + @Setter + @OutputFile + private Property outputFile; + + @Getter + @Setter + @Input + private Property showArtifacts; + + private final JavaPluginConvention javaPluginConvention; + + + @InputFiles + public Provider getConfigurationFiles() { + return configurationName.flatMap(name -> getProject().getConfigurations().named(name)); + } + + @Option(option = "configuration", description = "Set the configuration name") + public void setConfiguration(String configurationName) { + this.configurationName.set(configurationName); + } + + @Option(option = "output", description = "Set the output file name") + public void setOutput(String outputFile) { + this.outputFile.set(getProject().file(outputFile)); + } + + @Option(option = "showArtifacts", description = "Show artifacts") + public void setArtifacts(boolean value) { + showArtifacts.set(value); + } + + @Inject + public ExportDependencies(ObjectFactory objects) { + javaPluginConvention = getProject().getConvention().getPlugin(JavaPluginConvention.class); + configurationName = objects.property(String.class).convention("runtimeClasspath"); + outputFile = objects.property(File.class).convention( + getProject().provider(() -> new File(javaPluginConvention.getDocsDir(), "dependencies.dot"))); + showArtifacts = objects.property(Boolean.class).convention(false); + } + + private static String quote(String s) { + return "\"" + s + "\""; + } + + @TaskAction + @SneakyThrows + void run() { + Map map = new HashMap<>(); + + Configuration requestedConfiguration = Optional.ofNullable(getProject().getConfigurations().named(configurationName.get()).getOrNull()).orElseThrow(() -> { + String resolvableConfigurations = '[' + getProject().getConfigurations().stream() + .filter(Configuration::isCanBeResolved) + .map(it -> '\'' + it.getName() + '\'') + .collect(Collectors.joining(", ")) + ']'; + throw new GradleException(String.format("Configuration '%s' doesn't exist or cannot be resolved, " + + "resolvable configurations in this project are %s", configurationName.get(), resolvableConfigurations)); + }); + ResolutionResult resolutionResult = requestedConfiguration.getIncoming().getResolutionResult(); + Path destination = outputFile.map(it -> { + if (it.isAbsolute()) { + return it; + } else { + return new File(javaPluginConvention.getDocsDir(), it.toString()); + } + }).map(File::toPath).get(); + Files.createDirectories(destination.getParent()); + try(Writer writer = Files.newBufferedWriter(destination)) { + writer.write("digraph G {"); + writer.write('\n'); + writer.write(" #rankdir=\"LR\";"); + writer.write('\n'); + Optional>> artifactMap = Optional.empty(); + if(showArtifacts.get()) { + artifactMap = Optional.of(requestedConfiguration.getResolvedConfiguration().getResolvedArtifacts().stream().map(it -> + new AbstractMap.SimpleEntry<>(it.getId().getComponentIdentifier(), it) + ).collect(Collectors.groupingBy(Map.Entry::getKey, + Collector.of(ArrayList::new, + (list, entry) -> list.add(entry.getValue()), + (l1, l2) -> { l1.addAll(l2); return l1; })))); + } + final int[] sequence = new int[1]; + for (ResolvedComponentResult component : resolutionResult.getAllComponents()) { + map.computeIfAbsent(component, it -> sequence[0]++); + ComponentIdentifier id = component.getId(); + Optional> artifacts = artifactMap + .flatMap(it -> Optional.ofNullable(it.get(id))); + String componentName = id.getDisplayName(); + String label = artifacts.map(it -> { + String rows = it.stream().map(resolvedArtifact -> { + String artifactDescription = Stream.of( + new AbstractMap.SimpleEntry<>("type", resolvedArtifact.getType()), + new AbstractMap.SimpleEntry<>("classifier", resolvedArtifact.getClassifier()), + new AbstractMap.SimpleEntry<>("extension", + !Objects.equals(resolvedArtifact.getExtension(), resolvedArtifact.getType()) ? + resolvedArtifact.getExtension() : null) + ).map(entry -> { + if (entry.getValue() == null || entry.getValue().isEmpty()) return null; + else return entry.getKey() + ": " + entry.getValue(); + }).collect(Collectors.joining(", ")); + return "" + artifactDescription + ""; + }).collect(Collectors.joining()); + return "<" + + " " + + " " + + " " + + " " + rows + + "
" + id.getDisplayName() + "
>"; + }).orElse(quote(componentName)); + + String shape; + String color; + if(id instanceof ProjectComponentIdentifier) { + shape = artifacts.isEmpty() ? "box" : "none"; + color = "#88ff88"; + } else if(id instanceof ModuleComponentIdentifier) { + shape = artifacts.isEmpty() ? "oval" : "none"; + color = "#ffff88"; + } else { + throw new IllegalArgumentException(id.getClass().getName()); + } + Map attrs = Stream.of( + new AbstractMap.SimpleEntry<>("label", label), + new AbstractMap.SimpleEntry<>("shape", quote(shape)), + new AbstractMap.SimpleEntry<>("style", quote("filled")), + artifacts.map(it -> new AbstractMap.SimpleEntry<>("margin", quote("0"))).orElse(null), + new AbstractMap.SimpleEntry<>("fillcolor", quote(color)) + ).filter(Objects::nonNull).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + writer.write(" node_" + map.get(component) + " [" + + attrs.entrySet().stream() + .map(it -> it.getKey() + '=' + it.getValue()) + .collect(Collectors.joining(", ")) + + "];"); + writer.write('\n'); + } + + @EqualsAndHashCode + @RequiredArgsConstructor + class Link { + final ComponentIdentifier id1; + final ComponentIdentifier id2; + } + Set linkCache = new HashSet<>(); + for (ResolvedComponentResult component : resolutionResult.getAllComponents()) { + for(DependencyResult dependency : component.getDependencies()) { + if(dependency instanceof ResolvedDependencyResult) { + ResolvedComponentResult child = + ((ResolvedDependencyResult) dependency).getSelected(); + if(linkCache.add(new Link(component.getId(), child.getId()))) { + writer.write(" node_" + map.get(component) + " -> node_" + map.get(child) + ";"); + writer.write('\n'); + } + } else if(dependency instanceof UnresolvedDependencyResult) { + throw ((UnresolvedDependencyResult) dependency).getFailure(); + } else { + throw new IllegalArgumentException(dependency.getClass().getName()); + } + } + } + writer.write('}'); + writer.write('\n'); + } + } +} diff --git a/dependency-export/src/main/java/net/woggioni/gradle/dependency/export/RenderDependencies.java b/dependency-export/src/main/java/net/woggioni/gradle/dependency/export/RenderDependencies.java new file mode 100644 index 0000000..e0ca4f2 --- /dev/null +++ b/dependency-export/src/main/java/net/woggioni/gradle/dependency/export/RenderDependencies.java @@ -0,0 +1,87 @@ +package net.woggioni.gradle.dependency.export; + +import lombok.Getter; +import lombok.Setter; +import lombok.SneakyThrows; +import org.gradle.api.DefaultTask; +import org.gradle.api.GradleException; +import org.gradle.api.model.ObjectFactory; +import org.gradle.api.plugins.JavaPluginConvention; +import org.gradle.api.provider.Property; +import org.gradle.api.provider.Provider; +import org.gradle.api.tasks.InputFile; +import org.gradle.api.tasks.TaskAction; +import org.gradle.api.tasks.options.Option; + +import javax.inject.Inject; +import java.io.File; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; + +public class RenderDependencies extends DefaultTask { + + @Getter + @InputFile + private Provider sourceFile; + + @Getter + @Setter + private Property format; + + @Getter + @Setter + private Property graphvizExecutable; + + @Getter + @Setter + private Property outputFile; + + private final JavaPluginConvention javaPluginConvention; + + @Option(option = "output", description = "Set the output file name") + public void setOutputCli(String outputFile) { + this.outputFile.set(getProject().file(outputFile)); + } + + @Option(option = "format", description = "Set output format (see https://graphviz.org/doc/info/output.html)") + public void setFormatCli(String format) { + this.format.set(format); + } + + public void setExportTask(Provider taskProvider) { + sourceFile = taskProvider.flatMap(ExportDependencies::getOutputFile); + } + + @Inject + public RenderDependencies(ObjectFactory objects) { + sourceFile = objects.property(File.class); + javaPluginConvention = getProject().getConvention().getPlugin(JavaPluginConvention.class); + format = objects.property(String.class).convention("xlib"); + graphvizExecutable = objects.property(String.class).convention("dot"); + outputFile = objects.property(File.class) + .convention(new File(javaPluginConvention.getDocsDir(), "renderedDependencies")); + } + + @TaskAction + @SneakyThrows + void run() { + Path destination = outputFile.map(it -> { + if (it.isAbsolute()) { + return it; + } else { + return new File(javaPluginConvention.getDocsDir(), it.toString()); + } + }).map(File::toPath).get(); + List cmd = Arrays.asList( + graphvizExecutable.get(), + "-T" + format.get(), + "-o" + destination.toString(), + sourceFile.get().toString() + ); + int returnCode = new ProcessBuilder(cmd).inheritIO().start().waitFor(); + if (returnCode != 0) { + throw new GradleException("Error invoking graphviz"); + } + } +} diff --git a/dependency-export/src/main/kotlin/net/woggioni/plugins/dependency/export/DependencyExportPlugin.kt b/dependency-export/src/main/kotlin/net/woggioni/plugins/dependency/export/DependencyExportPlugin.kt deleted file mode 100644 index 78c3f80..0000000 --- a/dependency-export/src/main/kotlin/net/woggioni/plugins/dependency/export/DependencyExportPlugin.kt +++ /dev/null @@ -1,220 +0,0 @@ -package net.woggioni.plugins.dependency.export - -import org.gradle.api.GradleException -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.artifacts.ResolvedArtifact -import org.gradle.api.artifacts.component.ComponentIdentifier -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.Path -import java.nio.file.Paths -import kotlin.reflect.KMutableProperty0 - - -open class ExportDependenciesPluginExtension(project: Project) { - var configurationName: String = "default" - var outputFile = project.buildDir.toPath().resolve("dependencies.dot") - var showArtifacts = false -} - -open class RenderDependenciesPluginExtension(project: Project) { - var format: String = "xlib" - var outputFile = project.buildDir.toPath().resolve("renderedDependencies") - var graphvizExecutable: String = "dot" -} - -private class Overrider(private val properties: Map, private val prefix: String) { - inline fun identity(arg: T): T { - return arg - } - - fun overrideProperty(property: KMutableProperty0) { - overrideProperty(property, ::identity) - } - - inline fun overrideProperty( - property: KMutableProperty0, - valueFactory: (String) -> V) { - val propertyKey = prefix + "." + property.name - val propertyValue = properties[propertyKey] as String? - if (propertyValue != null) { - property.set(valueFactory(propertyValue)) - } - } -} - -object DependencyExporter { - - private fun quote(s : String) = "\"" + s + "\"" - - fun exportDot(project: Project, ext: ExportDependenciesPluginExtension) { - val overrider = Overrider(project.properties, "exportDependencies") - overrider.overrideProperty(ext::configurationName) - overrider.overrideProperty(ext::outputFile) { value -> Paths.get(value) } - overrider.overrideProperty(ext::showArtifacts) { value -> value.toBoolean() } - - var sequence = 0 - val map = HashMap() - - val requestedConfiguration = project.configurations.singleOrNull { - it.name == ext.configurationName - }?.takeIf { it.isCanBeResolved } ?: let { - val resolvableConfigurations = "[" + project.configurations.asSequence() - .filter { it.isCanBeResolved } - .map { "'${it.name}'" } - .joinToString(",") + "]" - throw GradleException("Configuration '${ext.configurationName}' doesn't exist or cannot be resolved, " + - "resolvable configurations in this project are " + resolvableConfigurations) - } - - val resolutionResult = requestedConfiguration.incoming.resolutionResult - if (!ext.outputFile.isAbsolute) { - ext.outputFile = project.buildDir.toPath().resolve(ext.outputFile) - } - Files.createDirectories(ext.outputFile.parent) - BufferedWriter( - OutputStreamWriter( - Files.newOutputStream(ext.outputFile))).use { writer -> - writer.write("digraph G {") - writer.newLine() - writer.write(" #rankdir=\"LR\";") - writer.newLine() - - val artifactMap = if(ext.showArtifacts) { - requestedConfiguration.resolvedConfiguration.resolvedArtifacts.asSequence().map { - it.id.componentIdentifier to it - }.groupBy( - Pair::first, - Pair::second - ) - } else { - null - } - - for (component in resolutionResult.allComponents) { - map.computeIfAbsent(component) { - sequence++ - } - val artifacts = artifactMap?.let { it[component.id] } - val (shape, color) = when (component.id) { - is ProjectComponentIdentifier -> (artifacts?.let { "none" } ?: "box") to "#88ff88" - is ModuleComponentIdentifier -> (artifacts?.let { "none" } ?: "oval") to "#ffff88" - else -> throw NotImplementedError("${component.id::class}") - } - - - val componentName = component.id.displayName - val label = artifacts?.let { - val rows = it.asSequence().map { resolvedArtifact -> - val artifactDescription = sequenceOf( - "type" to resolvedArtifact.type, - "classifier" to resolvedArtifact.classifier, - "extension" to resolvedArtifact.extension.takeIf { - resolvedArtifact.extension != resolvedArtifact.type - } - ).mapNotNull { pair -> - when { - pair.second == null || pair.second.isEmpty() -> null - else -> "${pair.first}: ${pair.second}" - } - }.joinToString(", ") - "$artifactDescription" - }.joinToString() - """ - < - - - - $rows -
${component.id.displayName}
> - """.trimIndent() - } ?: quote(componentName) - - val attrs = sequenceOf( - "label" to label, - "shape" to quote(shape), - "style" to quote("filled"), - artifacts?.let { "margin" to quote(0.toString()) }, - "fillcolor" to quote(color) - ).mapNotNull { it }.toMap() - 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() - } - } -} - -object DependencyRenderer { - fun render(project: Project, ext: RenderDependenciesPluginExtension, sourceFile: Path) { - val overrider = Overrider(project.properties, "renderDependencies") - overrider.overrideProperty(ext::format) - overrider.overrideProperty(ext::graphvizExecutable) - overrider.overrideProperty(ext::outputFile) { value -> Paths.get(value) } - - if (!ext.outputFile.isAbsolute) { - ext.outputFile = project.buildDir.toPath().resolve(ext.outputFile) - } - val cmd: List = listOf( - ext.graphvizExecutable, - "-T${ext.format}", - "-o${ext.outputFile}", - sourceFile.toString() - - ) - val returnCode = ProcessBuilder(cmd).inheritIO().start().waitFor() - if (returnCode != 0) { - throw GradleException("Error invoking graphviz") - } - } -} - -class DependencyExportPlugin : Plugin { - override fun apply(project: Project) { - val dependencyExportExtension = ExportDependenciesPluginExtension(project) - project.extensions.add(ExportDependenciesPluginExtension::class.java, "exportDependencies", dependencyExportExtension) - val exportDependenciesTask = project.tasks.register("exportDependencies") { - it.doLast { - DependencyExporter.exportDot(project, dependencyExportExtension) - } - }.get() - - val renderDependenciesPluginExtension = RenderDependenciesPluginExtension(project) - project.extensions.add(RenderDependenciesPluginExtension::class.java, "renderDependencies", renderDependenciesPluginExtension) - project.tasks.register("renderDependencies") { - it.dependsOn(exportDependenciesTask) - it.doLast { - DependencyRenderer.render(project, renderDependenciesPluginExtension, dependencyExportExtension.outputFile) - } - }.get() - } -} diff --git a/dependency-export/src/test/java/net/woggioni/gradle/dependency/export/DependencyExportPluginTest.java b/dependency-export/src/test/java/net/woggioni/gradle/dependency/export/DependencyExportPluginTest.java new file mode 100644 index 0000000..a06f25a --- /dev/null +++ b/dependency-export/src/test/java/net/woggioni/gradle/dependency/export/DependencyExportPluginTest.java @@ -0,0 +1,93 @@ +package net.woggioni.gradle.dependency.export; + +import lombok.SneakyThrows; +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.FileNotFoundException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.Objects; +import java.util.Optional; +import java.util.function.BiFunction; +import java.util.stream.Stream; + +public class DependencyExportPluginTest { + + private static InputStream resourceFromClass(Class cls, String resourceName) { + return cls.getResourceAsStream(resourceName); + } + + private static InputStream resourceFromClassLoader(Class cls, String resourceName) { + return cls.getClassLoader().getResourceAsStream(resourceName); + } + + @SneakyThrows + private static void installResource(Class cls, String resourceName, Path destination) { + Path outputFile; + Path realDestination; + if (Files.isSymbolicLink(destination)) { + realDestination = destination.toRealPath(); + } else { + realDestination = destination; + } + if(!Files.exists(realDestination)) { + Files.createDirectories(realDestination.getParent()); + outputFile = realDestination; + } else if(Files.isDirectory(realDestination)) { + outputFile = realDestination.resolve(resourceName.substring(1 + resourceName.lastIndexOf('/'))); + } else if(Files.isRegularFile(realDestination)) { + outputFile = realDestination; + } else throw new IllegalStateException("Path '${realDestination}' is neither a file nor a directory"); + Optional inputStreamOptional = Stream., String, InputStream>>of( + DependencyExportPluginTest::resourceFromClass, + DependencyExportPluginTest::resourceFromClassLoader + ).map(f -> f.apply(cls, resourceName)).filter(Objects::nonNull).findFirst(); + try(InputStream inputStream = inputStreamOptional.orElseThrow(() -> new FileNotFoundException(resourceName))){ + Files.copy(inputStream, outputFile, StandardCopyOption.REPLACE_EXISTING); + } + } + + @TempDir + public Path testGradleHomeDir; + + @TempDir + public Path testProjectDir; + + public Path buildFile; + + @BeforeEach + public void setup() { + buildFile = testProjectDir.resolve("build.gradle.kts"); + } + + public GradleRunner getStandardGradleRunnerFor(String taskName) { + return GradleRunner.create() + .withDebug(true) + .withProjectDir(testProjectDir.toFile()) + .withArguments(taskName, "-s", "--info", "-g", testGradleHomeDir.toString()) + .withPluginClasspath(); + } + + @Test + public void testKotlin() { + installResource(getClass(), "build.gradle.kts", testProjectDir); + installResource(getClass(),"settings.gradle.kts", testProjectDir); + installResource(getClass(),"gradle.properties", testProjectDir); + GradleRunner runner = getStandardGradleRunnerFor("exportDependencies"); + runner.build(); + } + + @Test + public void testGroovy() { + installResource(getClass(),"build.gradle", testProjectDir); + installResource(getClass(),"settings.gradle.kts", testProjectDir); + installResource(getClass(),"gradle.properties", testProjectDir); + GradleRunner runner = getStandardGradleRunnerFor("exportDependencies"); + runner.build(); + } +} diff --git a/dependency-export/src/test/kotlin/net/woggioni/plugins/dependency/export/DependencyExportPluginTest.kt b/dependency-export/src/test/kotlin/net/woggioni/plugins/dependency/export/DependencyExportPluginTest.kt deleted file mode 100644 index 98ceea2..0000000 --- a/dependency-export/src/test/kotlin/net/woggioni/plugins/dependency/export/DependencyExportPluginTest.kt +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This Kotlin source file was generated by the Gradle 'init' task. - */ -package net.woggioni.plugins.dependency.export - -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.nio.file.Path - - -class DependencyExportPluginTest { - - @TempDir - lateinit var testGradleHomeDir : Path - - @TempDir - lateinit var testProjectDir : Path - lateinit var buildFile : Path - - @BeforeEach - fun setup() { - buildFile = testProjectDir.resolve("build.gradle.kts") - } - - fun getStandardGradleRunnerFor(taskName: String): GradleRunner { - return GradleRunner.create() - .withDebug(true) - .withProjectDir(testProjectDir.toFile()) - .withArguments(taskName, "-s", "--info", "-g", testGradleHomeDir.toString()) - .withPluginClasspath() - } - - @Test - fun testKotlin() { - installResource("build.gradle.kts", testProjectDir) - installResource("settings.gradle.kts", testProjectDir) - installResource("gradle.properties", testProjectDir) - val runner = getStandardGradleRunnerFor("exportDependencies") - runner.build() - } - - @Test - fun testGroovy() { - installResource("build.gradle", testProjectDir) - installResource("settings.gradle.kts", testProjectDir) - installResource("gradle.properties", testProjectDir) - val runner = getStandardGradleRunnerFor("exportDependencies") - runner.build() - } -} diff --git a/dependency-export/src/test/kotlin/net/woggioni/plugins/dependency/export/Powerup.kt b/dependency-export/src/test/kotlin/net/woggioni/plugins/dependency/export/Powerup.kt deleted file mode 100644 index b9a3c4b..0000000 --- a/dependency-export/src/test/kotlin/net/woggioni/plugins/dependency/export/Powerup.kt +++ /dev/null @@ -1,33 +0,0 @@ -package net.woggioni.plugins.dependency.export - -import java.io.FileNotFoundException -import java.io.IOException -import java.nio.file.Files -import java.nio.file.Path -import java.nio.file.StandardCopyOption - - -@Throws(IOException::class) -fun Any.installResource(resourceName: String, destination: Path) { - val outputFile = run { - val realDestination = if (Files.isSymbolicLink(destination)) { - destination.toRealPath() - } else { - destination - } - when { - !Files.exists(realDestination) -> { - Files.createDirectories(realDestination.parent) - realDestination - } - Files.isDirectory(realDestination) -> - realDestination.resolve(resourceName.substring(1 + resourceName.lastIndexOf('/'))) - Files.isRegularFile(realDestination) -> realDestination - else -> throw IllegalStateException("Path '${realDestination}' is neither a file nor a directory") - } - } - (javaClass.getResourceAsStream(resourceName) - ?: javaClass.classLoader.getResourceAsStream(resourceName))?.use { inputStream -> - Files.copy(inputStream, outputFile, StandardCopyOption.REPLACE_EXISTING) - } ?: throw FileNotFoundException(resourceName) -} diff --git a/dependency-export/src/test/resources/net/woggioni/gradle/dependency/export/build.gradle b/dependency-export/src/test/resources/net/woggioni/gradle/dependency/export/build.gradle new file mode 100644 index 0000000..51fc278 --- /dev/null +++ b/dependency-export/src/test/resources/net/woggioni/gradle/dependency/export/build.gradle @@ -0,0 +1,18 @@ +plugins { + id 'java-library' + id "net.woggioni.gradle.dependency-export" +} + +exportDependencies { + configurationName = 'compileClasspath' +} + +repositories { + jcenter() + mavenLocal() +} + +dependencies { + runtimeOnly("org.hibernate:hibernate-core:5.4.13.Final") +} + diff --git a/dependency-export/src/test/resources/net/woggioni/gradle/dependency/export/build.gradle.kts b/dependency-export/src/test/resources/net/woggioni/gradle/dependency/export/build.gradle.kts new file mode 100644 index 0000000..c516eab --- /dev/null +++ b/dependency-export/src/test/resources/net/woggioni/gradle/dependency/export/build.gradle.kts @@ -0,0 +1,17 @@ +plugins { + id("java-library") + id("net.woggioni.gradle.dependency-export") +} + +repositories { + jcenter() + mavenLocal() +} + +dependencies { + runtimeOnly("org.hibernate:hibernate-core:5.4.13.Final") +} + +tasks.named("exportDependencies") { + configurationName.set("compileClasspath") +} diff --git a/dependency-export/src/test/resources/net/woggioni/plugins/dependency/export/build.gradle b/dependency-export/src/test/resources/net/woggioni/plugins/dependency/export/build.gradle deleted file mode 100644 index 477a53d..0000000 --- a/dependency-export/src/test/resources/net/woggioni/plugins/dependency/export/build.gradle +++ /dev/null @@ -1,17 +0,0 @@ -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") -} \ No newline at end of file diff --git a/dependency-export/src/test/resources/net/woggioni/plugins/dependency/export/build.gradle.kts b/dependency-export/src/test/resources/net/woggioni/plugins/dependency/export/build.gradle.kts deleted file mode 100644 index 71b1bbb..0000000 --- a/dependency-export/src/test/resources/net/woggioni/plugins/dependency/export/build.gradle.kts +++ /dev/null @@ -1,14 +0,0 @@ -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") -} - diff --git a/gradle.properties b/gradle.properties index 303ffd5..95a9653 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,6 @@ +version.kotlin=1.3.72 +version.gradlePublish=0.10.1 +version.lombok=1.18.16 +version.slf4j=1.7.30 version.junitJupiter=5.7.0 version.junitPlatform=1.7.0 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 62d4c053550b91381bbd28b1afc82d634bf73a8a..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f 100644 GIT binary patch delta 6656 zcmY+Ibx_pN*Z*PZ4(U#j1qtbvrOTyO8fghZ8kYJfEe%U|$dV!@ASKczEZq$fg48M@ z;LnHO_j#Uq?%bL4dY^md%$$4Y+&@nKC|1uHR&59YNhubGh72|a#ylPdh9V+akp|I; zPk^W-a00GrFMkz_NSADdv2G2-i6rb=cB_@WnG(**4ZO$=96R=t|NZ@|0_z&q3GwO^ ziUFcuj$a9QaZ3j?xt`5#q`sT-ufrtBP0nt3IA&dr*+VCsBzBVW?vZ6eZr0oD%t33z zm~-5IVsjy(F>;S~Pm@bxX85>Z*@(QL6i3JQc?1ryQFcC@X^2^mZWhFv|v? z49>l|nA&XNQ6#OvccUTyBMB*WO#NA;FW5|eE_K6dtVYP2G?uUZ09!`Iq1IF2gA(aS zLu@G^cQJmh=x?-YsYa@E6QnE5+1@ds&0f#OQRDl^GnIT_m84G5XY%W z;Ck6bk^Oeu*Ma-XmxI5GjqzWNbJMsQF4)WfMZEA{oxW0E32e)*JfG}3otPishIQBw zkBe6N#4pKPN>q1R6G1@5&(u#5yPEToMBB6_oEK|q z@(i5j!?;NNCv~=HvW%zF&1yWBq(nJa_#``G&SRmQvE|jePUPs{J!$TacM|e}Fsceb zx+76|mDp6@w>)^DIl{8?)6XYNRU|2plG8Jy&7(^9SdOWNKKJK&>0!z6XiN4J*Jkao z=E1y5x-XDC==Ub+8fLb#OW&{2ww{h^xlJFYAMOUd)}Xg@j?ak{7Kno6?9S~F?|6Df zHo|ijXX~`Sp;Vf!nR;m%vUhq>zvlRXsL0u*Tt?F#yR}3tF0#of{(UjitqST|!{aBA zicWh+URU}Jnc*sg9iMkf0pggpd?3TI*C-q$2QOdCC7rV+CHBmjS3O%a3VeZ$ZSs5ubJuJp%e%$LHgrj0niYjX;4kt z&2~j%@q3MO)-QGCA{>o%eZu){ou^MgC6~Z8Y=tc!qF=|TOlG3wJXbaLYr-;$Ch=2J z_UcE59Xzq&h0LsjLrcZrQSa}#=0~Lk|4?e4M z6d;v->NCC1oMti)RRc`Ys0?JXQjsZ@VdCy%Z)TptCrI>0Tte$pR!@yJesoU2dtyuW z7iFsE8)CkbiJP+OP28;(%?!9WddQZcAid@R@`*e%3W65$g9ee`zvwb(VPO+uVBq6p z{QDR%CR(2z@?&9Obm3xPi2lzvfip`7q`_7UDD|lRS}4=bsl3xQIOi0@GSvMuDQX}* z4B^(DI<${qUhcLqO`itJU;e<%%iS+R3I^_xIV1O%sp*x~;-dn` zt$8>RnSUh#rU3{-47067W^WNwTdq-t$-U>Hj%r!GD!gLa;kV zW5g6pCqV+!q8LgrI49(}fIc5K_`FLV4_E#XZ6{<>w8wzc%V9k!!Byg5-0WY+J?1*z%9~Aj4WQr1Jsn2(G!U8fFpi(wsy@JLg^d+IB0kl89 z0@Ssqf!L9JjYKK$J=978+NO*5^C)GPH2a%4hm$HROjM|N3g9ch9kDLh*nlwqy{mVM z`P(l#>3NnK%#O8tSb(VmZrG+`dRD#=Cc1P%(y5S?*Hj5E{vg&Eiw!YV>S#7_WRDVoFxT5m=gFi4)}y5V%KT8!xbsH_rmR& zsmM?%J}K$1l8d?2+m(}2c}-G`x>CY%Y&QBJRC$sKM}zN<9{IlF@yJEG<^0={$+`Hc zDodJ)gCADJ_bD#am(c2ojXKb|j+ENJ#58PAA&pZXufrFzBwnuuo+khfMgd!DMlU#v z9|JelQO~E2;d^w!RZJbt%IANIudpKSP)cssoWhq)>({nvcfCr0=9=FAIMuZm8Eo=} z|DND}8_PB5HqG(QwDvaM@orYBZ9kCkHV*rxKTy>q7n~0emErUwLbhq;VN<2nKT&*a2Ajz z;lKBzU2i8KLV`d)Y&ae)!HcGk$dO}Or%8KF@kE@jU1h@zwpw{6p4ME|uC$Za-ERR2 ztQvL&uOZLe(k{w_+J^ng+l}~N8MP>F1Z$fLu}D-WWaeu#XduP@#8JpmH(X>rIL)k3 zyXNyTIB1(IH%S&pQ{rWaTVfB$~-;RnlY z^(y7mR>@=brI>!TrA)BQsQ={b*6$=1Eqbuu6IdhJ&$YD$08AwtNr9*J?%-WT<;O1< zPl1<@yeqfZ>@s4azqTf<=I4(kU^+^Qkstm%WM-0_VLm({jFc8`5Df2Q1Y9zMZu0^! zsO_yh2Sz9K>Jq6fkYbBZocEJ6C!SdEzYDkiEtNJs{?!tA#e|oiN+VaaAobwKef_kUup&4scD?1+}Q8)DaekkMYn-FOS{J%NY za^mmJ^n`t*1p@hF*gl#L+5wr40*(ub4J#L|@oCl~@|4UvCjHBYDQv&S zhyGMAkRO^tF_dyi&XM)4mQ;k>kj?RgRo@-?==oD+ns*>bf@&fPXF|4U0&ib2 zo~1ZdmCPWf!W9#sGP@9X$;Rc`tjbz^&JY}z{}j9bl?;VC{x)TfQH$D^WowKL&4Zx@ zdSn+QV7H(e0xRfN6aBfH)Q=@weoD?dvu6^ZS)zqb>GwMmIuS8zJfaMUQx9>%k~w34 z3}_B2Jj~u=SnJ~vZPj*)UoDi_FtT=UAb#J^b4B%R6z3H%cj-1OCjU5F$ky>By1zsg z>2A0ccp29(Y<;my|J_g-r{1I@+*O$>!R3`_sFNP4e}LD1e1mM&SA`;;TR0I`_hESV zh4U*9ecK$0=lYk`{SR_cm$}iS*?yQR(}T-5ub?Wn^#RTe*^1~ya%`!xWq-F*WH@%nnZTNREA z3eUX2uM9b_w!Zo$nVTotEtzuL(88N)H~v_G=89|(@IFz~Wq6ME);z(!2^PkR2B&kE zxR)xV8PE|Hszyjp#jNf=ZIQ7JR~4Ls#Vd@mPF(7R5VO$akUq8JM+sn>ZVg(lJZ)5qjqdw(*7tuwjY#0tx+|!sTz9yV~%HOdrb#!5w9>*0LrCS z%wF$Yc6~hqVQZzoC^D<(-h0aOtk}kn<<*xF61HQr<5}efY{zXXA+PaJG7vT&{Oz(@Uu!V#Fp9%Ht!~@;6AcD z$lvlPu&yd(YnAHfpN51*)JN0aYw9gGk{NE7!Oqu4rBp}F30669;{zcH-a7w9KSpDQPIE_f9T zit? zJSjTKWbe{f{9BmSDAFO1(K0oqB4578tU0(oRBE^28X>xDA!1C&VJEiYak4_ZTM*7M`hv_ zw3;2ndv3X$zT!wa7TrId{gNE`Vxf}j5wsyX+;Kn<^$EJT`NzznjyYx=pYMkZjizEU zb;Gg8Pl_pqxg)9P)C)Hxh_-mQ;u-I_Ol>d^>q08zFF!>Z3j1-HmuME_TGZ*Ev;O0O z%e(edJfV<6t3&FKwtInnj9EeQhq9;o5oLJoiKwWF5bP2~Feh#P4oN()JT0pdq!9x* ze3D-1%AV#{G=Op$6q?*Z>s{qFn}cl@9#m@DK_Bs@fdwSN`Qe18_WnveRB583mdMG- z?<3pJC!YljOnO8=M=|Cg)jw;4>4sna`uI>Kh&F20jNOk9HX&}Ry|mHJ+?emHnbYLJ zwfkx@slh31+3nq-9G5FVDQBHWWY}&hJ-fpDf!lQdmw8dlTt#=)20X74S>c&kR(?PT zBg)Y%)q&|hW1K;`nJPAGF*c3{3`FvrhD9=Ld{3M*K&5$jRhXNsq$0CLXINax1AmXX ziF39vkNtcK6i^+G^AEY!WalGazOQ$_#tx?BQ{YY$&V&42sICVl8@AI6yv;sGnT;@f zL=}rZcJqNwrEEA=GDdEe8Z=f9>^?($oS8xGdFf1eUWTYtZF<3tu2V%noPBnd=thZ+ zO&xoc?jvXG7Xt!RTw#5VN50UjgqSntw9Y35*~pxz=8OzkXg{@S2J%+{l3Q>B_qbnl z20Deb7JM&ZSp`%X>xWpb>FF8q7Nq&4#a1}A-(-!aMDmVbz05D!NpUzVe{~72h%cOh zwQFNai2a$K|hFgDk(oPF_tuf{BV!=m0*xqSzGAJ(~XUh8rk#{YOg0ReK>4eJl z;-~u5v$}DM)#vER>F)-}y(X6rGkp<{AkiPM7rFgAV^)FUX8XmCKKaWlS4;MSEagj$ z#pvH`vLX1q{&eOm>htnk4hmv=_)ao!MCp}9ql5yfre&Py!~hBAGNBa}PH&J8K=~<% z&?!J-QaH|0bq_uo6rt*r-M>d7jm1cbW^T>s)S?L{n8v`^?VIPA+qi^6e@cM|5boqEO!p1e|_{7U3Yl6K?0xMN1bbjf0@$TE-T))w> zFe?E?g$PUT-)AJ(PS^By^D^Ed!K5iv$*_eW~VA(I3~UMy*ZcgVu0$XZC*_0PgDmUL)qTCn927LD~p$yXR_GCJ&iQ; z4*`%l-dC5pALH!y*nmhdHRh02QjW1vZL4ySucz*w3f|#`=u@@YvMV1?i!&DIa2+S< z8z!gvN3FV4I;%fl;ruFeV{jKjI~?GlgkmGBuJ<7vY|l3xMOc?S@Q#C(zo*m&JLrjT2rU9PYOniB8O~yO5<1CCcQz# z17B2m1Z{R!Y)UO#CU-Y&mOlv4*Gz%rC_YkRcO)jTUEWHDvv!GWmEihE>OKPx1J?Av z8J{-#7NsT>>R#*7**=QL)1@IR77G9JGZZiVt!=jD+i(oRV;I`JkiTSZkAXuHm-VG1 z+2-LD!!2dNEk@1@Rp|C$MD9mH^)H*G*wI(i*Rc6Vvdik+BDycYQ*=0JA3dxxha|Zg zCIW1Ye-DdpMGTEwbA^6hVC<(@0FL4dkDOYcxxC5c%MJQ^)zpA%>>~Q|Y=@)XW!px; z_Fx+xOo7>sz4QX|Ef~igE+uFnzFWP<-#||*V0`0p7E*+n5+awuOWmvR{-M*chIXgo zYiZvQMond#{F8+4Zh_;>MsaZUuhp=onH@P!7W>sq|CWv|u}Wg0vo&f4UtmLzhCwwu zJaR=IO;sQxS}h(K>9VZjnED+>9rGgB3ks+AwTy_EYH{oc)mo`451n&YH%A1@WC{;1 z=fB6n zIYp46_&u`COM&Di?$P}pPAlAF*Ss<)2Xc?=@_2|EMO?(A1u!Vc=-%bDAP#zDiYQvJ z0}+}3GaLxsMIlh6?f=iRs0K=RyvMOcWl*xqe-IBLv?K{S^hP)@K|$I+h_)pdD9r~! zxhw2u66+F(E`&6hY}B_qe>wil|#*0R0B;<@E?L zVrhXKfwRg0l8r>LuNs1QqW&39ME0sOXe8zycivGVqUOjEWpU)h|9fwp@d(8=M-WxY zeazSz6x5e`k821fgylLIbdqx~Kdh^Oj`Q!4vc*Km)^Tr-qRxPHozdvvU^#xNsKVr6aw8={70&S4y*5xeoF@Q^y596*09`XF56-N z1=Rm5?-An178o?$ix}y7gizQ9gEmGHF5AW+92DYaOcwEHnjAr~!vI>CK%h`E_tO8L Yte!%o?r4GTrVtxD61Ym!|5fq-1K$0e!T1w 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index bca17f3..80cf08e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index fbd7c51..4f906e0 100755 --- a/gradlew +++ b/gradlew @@ -130,7 +130,7 @@ fi if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath diff --git a/gradlew.bat b/gradlew.bat index 5093609..107acd3 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -54,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -64,21 +64,6 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line @@ -86,7 +71,7 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..f589015 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,15 @@ +pluginManagement { + repositories { + gradlePluginPortal() + } + + plugins { + id 'org.jetbrains.kotlin.jvm' version this['version.kotlin'] + id 'com.gradle.plugin-publish' version this['version.gradlePublish'] + } +} + +rootProject.name = "my-gradle-plugins" +include("dependency-export") +include("jpms-check") +include("multi-release-jar") diff --git a/settings.gradle.kts b/settings.gradle.kts deleted file mode 100644 index c90f1b5..0000000 --- a/settings.gradle.kts +++ /dev/null @@ -1,11 +0,0 @@ -pluginManagement { - plugins { - id("org.jetbrains.kotlin.jvm") version "1.3.72" apply false - id("com.gradle.plugin-publish") version "0.10.1" apply false - } -} - -rootProject.name = "my-gradle-plugins" -include("dependency-export") -include("jpms-check") -include("multi-release-jar")