diff --git a/COPYING b/COPYING index 22a0345..3a6e355 100644 --- a/COPYING +++ b/COPYING @@ -1,20 +1,7 @@ -Copyright © Tad Fisher and the gradle2nix contributors +Copyright © Tad Fisher and the gradle2nix contributors, and licensed +under the Apache License 2.0. -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: +Based on substantial portions of the GitHub Dependency Graph Gradle Plugin, +Copyright © Gradle, Inc and licensed under the Apache License 2.0. -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. \ No newline at end of file +See LICENSE for the full text of the Apache License 2.0. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f433b1a --- /dev/null +++ b/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 6efa4c6..3f194ea 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,27 +1,28 @@ -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile - plugins { - kotlin("jvm") - kotlin("kapt") + id("org.jetbrains.kotlin.jvm") + id("org.jetbrains.kotlin.plugin.serialization") application } +configurations { + register("share") +} + dependencies { - implementation(project(":model")) implementation(kotlin("reflect")) - implementation("org.gradle:gradle-tooling-api:${gradle.gradleVersion}") - implementation("com.github.ajalt:clikt:latest.release") - implementation("org.slf4j:slf4j-api:latest.release") - runtimeOnly("org.slf4j:slf4j-simple:latest.release") - implementation("com.squareup.moshi:moshi-adapters:latest.release") - implementation("com.squareup.moshi:moshi-kotlin:latest.release") - kapt("com.squareup.moshi:moshi-kotlin-codegen:latest.release") - implementation("com.squareup.okio:okio:latest.release") + implementation(project(":model")) + implementation(libs.clikt) + implementation(libs.gradle.toolingApi) + implementation(libs.serialization.json) + implementation(libs.slf4j.api) + runtimeOnly(libs.slf4j.simple) + implementation(libs.okio) + + "share"(project(":plugin", configuration = "shadow")) testRuntimeOnly(kotlin("reflect")) - testImplementation("org.spekframework.spek2:spek-dsl-jvm:latest.release") - testRuntimeOnly("org.spekframework.spek2:spek-runner-junit5:latest.release") - testImplementation("io.strikt:strikt-core:latest.release") + testImplementation(libs.kotest.assertions) + testImplementation(libs.kotest.runner) } application { @@ -29,11 +30,15 @@ application { applicationName = "gradle2nix" applicationDefaultJvmArgs += "-Dorg.nixos.gradle2nix.share=@APP_HOME@/share" applicationDistribution - .from(tasks.getByPath(":plugin:shadowJar"), "$rootDir/gradle-env.nix") + .from(configurations.named("share")) .into("share") .rename("plugin.*\\.jar", "plugin.jar") } +kotlin { + jvmToolchain(11) +} + sourceSets { test { resources { @@ -42,6 +47,8 @@ sourceSets { } } +val updateGolden = providers.gradleProperty("update-golden") + tasks { (run) { dependsOn(installDist) @@ -52,28 +59,32 @@ tasks { startScripts { doLast { - unixScript.writeText(unixScript.readText().replace("@APP_HOME@", "\$APP_HOME")) + unixScript.writeText( + unixScript.readText() + .replace("@APP_HOME@", "\\\"\$APP_HOME\\\"") + .replace(Regex("DEFAULT_JVM_OPTS=\'(.*)\'")) { match -> + "DEFAULT_JVM_OPTS=${match.groupValues[1]}" + } + ) windowsScript.writeText(windowsScript.readText().replace("@APP_HOME@", "%APP_HOME%")) } } - test { + withType { + notCompatibleWithConfigurationCache("huh?") dependsOn(installDist) doFirst { - systemProperties("org.nixos.gradle2nix.share" to installDist.get().destinationDir.resolve("share")) - } - useJUnitPlatform { - includeEngines("spek2") + if (updateGolden.isPresent) { + systemProperty("org.nixos.gradle2nix.update-golden", "") + } + systemProperties( + "org.nixos.gradle2nix.share" to installDist.get().destinationDir.resolve("share"), + "org.nixos.gradle2nix.m2" to rootDir.resolve("fixtures/repositories/m2").toURI().toString() + ) } + useJUnitPlatform() testLogging { events("passed", "skipped", "failed") } } - - withType { - kotlinOptions { - jvmTarget = "1.8" - freeCompilerArgs = listOf("-Xopt-in=kotlin.RequiresOptIn") - } - } } diff --git a/app/gradle.lockfile b/app/gradle.lockfile deleted file mode 100644 index 968ee4b..0000000 --- a/app/gradle.lockfile +++ /dev/null @@ -1,38 +0,0 @@ -# This is a Gradle generated file for dependency locking. -# Manual edits can break the build and are not advised. -# This file is expected to be part of source control. -com.christophsturm:filepeek:0.1.2=testRuntimeClasspath -com.github.ajalt:clikt:2.8.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.squareup.moshi:moshi-adapters:1.11.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.squareup.moshi:moshi-kotlin:1.11.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.squareup.moshi:moshi:1.11.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.squareup.okio:okio:3.0.0-alpha.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -io.github.classgraph:classgraph:4.8.37=testRuntimeClasspath -io.strikt:strikt-core:0.28.2=testCompileClasspath,testRuntimeClasspath -net.swiftzer.semver:semver:1.1.1=runtimeClasspath,testRuntimeClasspath -org.apiguardian:apiguardian-api:1.1.0=testRuntimeClasspath -org.gradle:gradle-tooling-api:6.8.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-reflect:1.4.20=compileClasspath,runtimeClasspath,testCompileClasspath -org.jetbrains.kotlin:kotlin-reflect:1.4.21-2=testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-common:1.4.20=compileClasspath,runtimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-common:1.4.21-2=testCompileClasspath,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.20=compileClasspath,runtimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.21-2=testCompileClasspath,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.20=compileClasspath,runtimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.21-2=testCompileClasspath,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib:1.4.20=compileClasspath,runtimeClasspath -org.jetbrains.kotlin:kotlin-stdlib:1.4.21-2=testCompileClasspath,testRuntimeClasspath -org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.3=testRuntimeClasspath -org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.4.2=testRuntimeClasspath -org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2=testRuntimeClasspath -org.jetbrains:annotations:13.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.junit.platform:junit-platform-commons:1.6.0=testRuntimeClasspath -org.junit.platform:junit-platform-engine:1.6.0=testRuntimeClasspath -org.junit:junit-bom:5.6.0=testRuntimeClasspath -org.opentest4j:opentest4j:1.2.0=testCompileClasspath,testRuntimeClasspath -org.slf4j:slf4j-api:2.0.0-alpha1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.slf4j:slf4j-simple:2.0.0-alpha1=runtimeClasspath,testRuntimeClasspath -org.spekframework.spek2:spek-dsl-jvm:2.0.15=testCompileClasspath,testRuntimeClasspath -org.spekframework.spek2:spek-runner-junit5:2.0.15=testRuntimeClasspath -org.spekframework.spek2:spek-runtime-jvm:2.0.15=testRuntimeClasspath -empty= diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/Artifact.kt b/app/src/main/kotlin/org/nixos/gradle2nix/Artifact.kt new file mode 100644 index 0000000..efa0d1c --- /dev/null +++ b/app/src/main/kotlin/org/nixos/gradle2nix/Artifact.kt @@ -0,0 +1,9 @@ +package org.nixos.gradle2nix + +import kotlinx.serialization.Serializable + +@Serializable +data class Artifact( + val urls: List, + val hash: String, +) diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/Env.kt b/app/src/main/kotlin/org/nixos/gradle2nix/Env.kt deleted file mode 100644 index 6c4135a..0000000 --- a/app/src/main/kotlin/org/nixos/gradle2nix/Env.kt +++ /dev/null @@ -1,50 +0,0 @@ -package org.nixos.gradle2nix - -import com.squareup.moshi.JsonClass - -@JsonClass(generateAdapter = true) -data class NixGradleEnv( - val name: String, - val version: String, - val path: String, - val gradle: DefaultGradle, - val dependencies: Map> -) - -fun buildEnv(builds: Map): Map = - builds.mapValues { (path, build) -> - NixGradleEnv( - name = build.rootProject.name, - version = build.rootProject.version, - path = path, - gradle = build.gradle, - dependencies = mapOf( - "settings" to build.settingsDependencies, - "plugin" to build.pluginDependencies, - "buildscript" to build.rootProject.collectDependencies(DefaultProject::buildscriptDependencies), - "project" to build.rootProject.collectDependencies(DefaultProject::projectDependencies) - ) - ) - } - -private fun DefaultProject.collectDependencies( - chooser: DefaultProject.() -> List -): List { - val result = mutableMapOf() - mergeRepo(result, chooser()) - for (child in children) { - mergeRepo(result, child.collectDependencies(chooser)) - } - return result.values.toList() -} - -private fun mergeRepo( - base: MutableMap, - extra: List -) { - extra.forEach { artifact -> - base.merge(artifact.id, artifact) { old, new -> - old.copy(urls = old.urls.union(new.urls).toList()) - } - } -} diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/GradleRunner.kt b/app/src/main/kotlin/org/nixos/gradle2nix/GradleRunner.kt index 4978ebe..a0368e8 100644 --- a/app/src/main/kotlin/org/nixos/gradle2nix/GradleRunner.kt +++ b/app/src/main/kotlin/org/nixos/gradle2nix/GradleRunner.kt @@ -13,19 +13,31 @@ fun connect(config: Config): ProjectConnection = .forProjectDirectory(config.projectDir) .connect() -@Suppress("UnstableApiUsage") -fun ProjectConnection.getBuildModel(config: Config, path: String): DefaultBuild { - return model(Build::class.java).apply { - addArguments( - "--init-script=$shareDir/init.gradle", - "-Porg.nixos.gradle2nix.configurations=${config.configurations.joinToString(",")}", - "-Porg.nixos.gradle2nix.subprojects=${config.subprojects.joinToString(",")}" - ) - if (config.gradleArgs != null) addArguments(config.gradleArgs) - if (path.isNotEmpty()) addArguments("--project-dir=$path") - if (!config.quiet) { - setStandardOutput(System.err) - setStandardError(System.err) +fun ProjectConnection.build( + config: Config, +) { + newBuild() + .apply { + if (config.tasks.isNotEmpty()) { + forTasks(*config.tasks.toTypedArray()) + } else { + forTasks(RESOLVE_ALL_TASK) + } + addArguments(config.gradleArgs) + addArguments( + "--init-script=${config.appHome}/init.gradle", + "--write-verification-metadata", "sha256" + ) + if (config.projectFilter != null) { + addArguments("-D${PARAM_INCLUDE_PROJECTS}") + } + if (config.configurationFilter != null) { + addArguments("-D${PARAM_INCLUDE_CONFIGURATIONS}") + } + if (config.logger.verbose) { + setStandardOutput(System.err) + setStandardError(System.err) + } } - }.get().let { DefaultBuild(it) } + .run() } diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/Logger.kt b/app/src/main/kotlin/org/nixos/gradle2nix/Logger.kt index 949249a..9191481 100644 --- a/app/src/main/kotlin/org/nixos/gradle2nix/Logger.kt +++ b/app/src/main/kotlin/org/nixos/gradle2nix/Logger.kt @@ -1,6 +1,7 @@ package org.nixos.gradle2nix import java.io.PrintStream +import kotlin.system.exitProcess class Logger( val out: PrintStream = System.err, @@ -9,9 +10,9 @@ class Logger( val log: (String) -> Unit = { if (verbose) out.println(it) } val warn: (String) -> Unit = { out.println("Warning: $it")} - val error: (String) -> Unit = { + val error: (String) -> Nothing = { out.println("Error: $it") - System.exit(1) + exitProcess(1) } operator fun component1() = log diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/Main.kt b/app/src/main/kotlin/org/nixos/gradle2nix/Main.kt index afe4c1b..921ac1b 100644 --- a/app/src/main/kotlin/org/nixos/gradle2nix/Main.kt +++ b/app/src/main/kotlin/org/nixos/gradle2nix/Main.kt @@ -1,102 +1,97 @@ package org.nixos.gradle2nix -import com.github.ajalt.clikt.completion.CompletionCandidates import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.context import com.github.ajalt.clikt.output.CliktHelpFormatter -import com.github.ajalt.clikt.parameters.arguments.ProcessedArgument import com.github.ajalt.clikt.parameters.arguments.argument -import com.github.ajalt.clikt.parameters.arguments.convert -import com.github.ajalt.clikt.parameters.arguments.default +import com.github.ajalt.clikt.parameters.arguments.multiple import com.github.ajalt.clikt.parameters.options.default import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.multiple import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.options.validate import com.github.ajalt.clikt.parameters.types.file -import com.squareup.moshi.Moshi -import com.squareup.moshi.Types -import okio.buffer -import okio.sink import java.io.File - -val shareDir: String = System.getProperty("org.nixos.gradle2nix.share") +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.encodeToStream data class Config( + val appHome: File, + val gradleHome: File, val gradleVersion: String?, - val gradleArgs: String?, - val configurations: List, + val gradleArgs: List, + val projectFilter: String?, + val configurationFilter: String?, val projectDir: File, - val includes: List, - val subprojects: List, - val buildSrc: Boolean, - val quiet: Boolean -) { - val allProjects = listOf(projectDir) + includes + val tasks: List, + val logger: Logger, +) + +@OptIn(ExperimentalSerializationApi::class) +private val JsonFormat = Json { + prettyPrint = true + prettyPrintIndent = " " } -class Main : CliktCommand( +class Gradle2Nix : CliktCommand( name = "gradle2nix" ) { - private val gradleVersion: String? by option("--gradle-version", "-g", + private val gradleVersion: String? by option( + "--gradle-version", "-g", metavar = "VERSION", - help = "Use a specific Gradle version") + help = "Use a specific Gradle version" + ) - private val gradleArgs: String? by option("--gradle-args", "-a", - metavar = "ARGS", - help = "Extra arguments to pass to Gradle") + private val projectFilter: String? by option( + "--projects", "-p", + metavar = "REGEX", + help = "Regex to filter Gradle projects (default: include all projects)" + ) - private val configurations: List by option("--configuration", "-c", - metavar = "NAME", - help = "Add a configuration to resolve (default: all configurations)") - .multiple() + private val configurationFilter: String? by option( + "--configurations", "-c", + metavar = "REGEX", + help = "Regex to filter Gradle configurations (default: include all configurations)") - private val includes: List by option("--include", "-i", - metavar = "DIR", - help = "Add an additional project to include") - .file(mustExist = true, canBeFile = false, canBeDir = true, mustBeReadable = true) - .multiple() - .validate { files -> - val failures = files.filterNot { it.isProjectRoot() } - if (failures.isNotEmpty()) { - val message = failures.joinToString("\n ") - fail("Included builds are not Gradle projects:\n$message\n" + - "Gradle projects must contain a settings.gradle or settings.gradle.kts script.") - } - } - - private val subprojects: List by option("--project", "-p", - metavar = "PATH", - help = "Only resolve these subproject paths, e.g. ':', or ':sub:project' (default: all projects)") - .multiple() - .validate { paths -> - val failures = paths.filterNot { it.startsWith(":") } - if (failures.isNotEmpty()) { - val message = failures.joinToString("\n ") - fail("Subproject paths must be absolute:\n$message\n" + - "Paths are in the form ':parent:child'.") - } - } - - val outDir: File? by option("--out-dir", "-o", + val outDir: File? by option( + "--out-dir", "-o", metavar = "DIR", help = "Path to write generated files (default: PROJECT-DIR)") .file(canBeFile = false, canBeDir = true) - val envFile: String by option("--env", "-e", + val envFile: String by option( + "--env", "-e", metavar = "FILENAME", help = "Prefix for environment files (.json and .nix)") .default("gradle-env") - private val buildSrc: Boolean by option("--build-src", "-b", help = "Include buildSrc project (default: true)") - .flag("--no-build-src", "-nb", default = true) - private val quiet: Boolean by option("--quiet", "-q", help = "Disable logging") .flag(default = false) - private val projectDir: File by argument("PROJECT-DIR", help = "Path to the project root (default: .)") - .projectDir() - .default(File(".")) + private val projectDir: File by option( + "--projectDir", "-d", + metavar = "PROJECT-DIR", + help = "Path to the project root (default: .)") + .file() + .default(File("."), "Current directory") + .validate { file -> + if (!file.exists()) fail("Directory \"$file\" does not exist.") + if (file.isFile) fail("Directory \"$file\" is a file.") + if (!file.canRead()) fail("Directory \"$file\" is not readable.") + if (!file.isProjectRoot()) fail("Directory \"$file\" is not a Gradle project.") + } + + private val tasks: List by option( + "--tasks", "-t", + metavar = "TASKS", + help = "Gradle tasks to run" + ).multiple() + + private val gradleArgs: List by argument( + name = "ARGS", + help = "Extra arguments to pass to Gradle" + ).multiple() init { context { @@ -107,65 +102,59 @@ class Main : CliktCommand( // Visible for testing lateinit var config: Config + @OptIn(ExperimentalSerializationApi::class) override fun run() { + val appHome = System.getProperty("org.nixos.gradle2nix.share") + if (appHome == null) { + System.err.println("Error: could not locate the /share directory in the gradle2nix installation") + } + val gradleHome = System.getenv("GRADLE_USER_HOME")?.let(::File) ?: File("${System.getProperty("user.home")}/.gradle") + val logger = Logger(verbose = !quiet) + config = Config( + File(appHome), + gradleHome, gradleVersion, gradleArgs, - configurations, + projectFilter, + configurationFilter, projectDir, - includes, - subprojects, - buildSrc, - quiet + tasks, + logger ) - val (log, _, _) = Logger(verbose = !config.quiet) - val paths = resolveProjects(config).map { p -> - p.toRelativeString(config.projectDir) - } + val (log, _, error) = logger - val models = connect(config).use { connection -> - paths.associateWith { project -> - log("Resolving project model: ${project.takeIf { it.isNotEmpty() } ?: "root project"}...") - connection.getBuildModel(config, project) + val metadata = File("$projectDir/gradle/verification-metadata.xml") + if (metadata.exists()) { + val backup = metadata.resolveSibling("verification-metadata.xml.bak") + if (metadata.renameTo(backup)) { + Runtime.getRuntime().addShutdownHook(Thread { + metadata.delete() + backup.renameTo(metadata) + }) } } - log("Building environment...") - val nixGradleEnv = buildEnv(models) + connect(config).use { connection -> + connection.build(config) + } + + val dependencies = try { + processDependencies(config) + } catch (e: Throwable) { + error("Dependency parsing failed: ${e.message}") + } val outDir = outDir ?: projectDir - val json = outDir.resolve("$envFile.json") log("Writing environment to $json") - - json.sink().buffer().use { out -> - Moshi.Builder().build() - .adapter>( - Types.newParameterizedType(Map::class.java, String::class.java, NixGradleEnv::class.java) - ) - .indent(" ") - .toJson(out, nixGradleEnv) - out.flush() - } - - val nix = outDir.resolve("$envFile.nix") - log("Writing Nix script to $nix") - - File(shareDir).resolve("gradle-env.nix").copyTo(nix, overwrite = true) - } -} - -fun ProcessedArgument.projectDir(): ProcessedArgument { - return convert(completionCandidates = CompletionCandidates.Path) { - File(it).also { file -> - if (!file.exists()) fail("Directory \"$file\" does not exist.") - if (file.isFile) fail("Directory \"$file\" is a file.") - if (!file.canRead()) fail("Directory \"$file\" is not readable.") - if (!file.isProjectRoot()) fail("Directory \"$file\" is not a Gradle project.") + json.outputStream().buffered().use { output -> + JsonFormat.encodeToStream(dependencies, output) } } } -fun main(args: Array) = Main().main(args) - +fun main(args: Array) { + Gradle2Nix().main(args) +} diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/Process.kt b/app/src/main/kotlin/org/nixos/gradle2nix/Process.kt new file mode 100644 index 0000000..1b6b1e2 --- /dev/null +++ b/app/src/main/kotlin/org/nixos/gradle2nix/Process.kt @@ -0,0 +1,207 @@ +package org.nixos.gradle2nix + +import java.io.File +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.decodeFromStream +import okio.ByteString.Companion.decodeHex +import okio.HashingSource +import okio.blackholeSink +import okio.buffer +import okio.source +import org.nixos.gradle2nix.dependency.ModuleComponentIdentifier +import org.nixos.gradle2nix.dependencygraph.model.DependencyCoordinates +import org.nixos.gradle2nix.dependencygraph.model.Repository +import org.nixos.gradle2nix.dependencygraph.model.ResolvedConfiguration +import org.nixos.gradle2nix.metadata.ArtifactVerificationMetadata +import org.nixos.gradle2nix.metadata.Checksum +import org.nixos.gradle2nix.metadata.ChecksumKind +import org.nixos.gradle2nix.metadata.ComponentVerificationMetadata +import org.nixos.gradle2nix.metadata.DependencyVerificationsXmlReader +import org.nixos.gradle2nix.metadata.DependencyVerifier + +// Local Maven repository for testing +private val m2 = System.getProperty("org.nixos.gradle2nix.m2") + +private fun shouldSkipRepository(repository: Repository): Boolean { + return repository.artifactResources.all { it.startsWith("file:") && (m2 == null || !it.startsWith(m2)) } || + repository.metadataResources.all { it.startsWith("file:") && (m2 == null || !it.startsWith(m2)) } +} + +fun processDependencies(config: Config): Map> { + val verifier = readVerificationMetadata(config) + val configurations = readDependencyGraph(config) + + val repositories = configurations + .flatMap { it.repositories } + .associateBy { it.id } + .filterNot { (id, repo) -> + if (shouldSkipRepository(repo)) { + config.logger.warn("$id: all URLs are files; skipping") + true + } else { + false + } + } + if (repositories.isEmpty()) { + config.logger.warn("no repositories found in any configuration") + return emptyMap() + } + + return configurations.asSequence() + .flatMap { it.allDependencies.asSequence() } + .groupBy { it.id } + .mapNotNull { (id, dependencies) -> + val deps = dependencies.toSet() + if (deps.isEmpty()) { + config.logger.warn("$id: no resolved dependencies in dependency graph") + return@mapNotNull null + } + val coordinates = deps.first().coordinates + val componentId = ModuleComponentIdentifier( + coordinates.group, + coordinates.module, + coordinates.version + ) + val metadata = verifier.verificationMetadata[componentId] + ?: verifyComponentFilesInCache(config, componentId) + if (metadata == null) { + config.logger.warn("$id: not present in metadata or cache; skipping") + return@mapNotNull null + } + + val repoIds = dependencies.mapNotNull { it.repository } + if (repoIds.isEmpty()) { + config.logger.warn("$id: no repository ids in dependency graph; skipping") + return@mapNotNull null + } + val repos = repoIds.mapNotNull(repositories::get) + if (repos.isEmpty()) { + config.logger.warn("$id: no repositories found for repository ids $repoIds; skipping") + return@mapNotNull null + } + + id to metadata.artifactVerifications.associate { meta -> + meta.artifactName to Artifact( + urls = repos + .flatMap { repository -> artifactUrls(coordinates, meta, repository) } + .distinct(), + hash = meta.checksums.maxBy { c -> c.kind.ordinal }.toSri() + ) + } + } + .toMap() +} + +private fun readVerificationMetadata(config: Config): DependencyVerifier { + return config.projectDir.resolve("gradle/verification-metadata.xml") + .inputStream() + .buffered() + .use { input -> DependencyVerificationsXmlReader.readFromXml(input) } +} + +@OptIn(ExperimentalSerializationApi::class) +private fun readDependencyGraph(config: Config): List { + return config.projectDir.resolve("build/reports/nix-dependency-graph/dependency-graph.json") + .inputStream() + .buffered() + .use { input -> Json.decodeFromStream(input) } +} + +private fun verifyComponentFilesInCache( + config: Config, + component: ModuleComponentIdentifier +): ComponentVerificationMetadata? { + val cacheDir = config.gradleHome.resolve("caches/modules-2/files-2.1/${component.group}/${component.module}/${component.version}") + if (!cacheDir.exists()) { + return null + } + val verifications = cacheDir.walkBottomUp().filter { it.isFile }.map { f -> + ArtifactVerificationMetadata( + f.name, + listOf(Checksum(ChecksumKind.sha256, f.sha256())) + ) + } + config.logger.log("$component: obtained artifact hashes from Gradle cache.") + return ComponentVerificationMetadata(component, verifications.toList()) +} + +private fun File.sha256(): String { + val source = HashingSource.sha256(source()) + source.buffer().readAll(blackholeSink()) + return source.hash.hex() +} + +private fun Checksum.toSri(): String { + val hash = value.decodeHex().base64() + return when (kind) { + ChecksumKind.md5 -> "md5-$hash" + ChecksumKind.sha1 -> "sha1-$hash" + ChecksumKind.sha256 -> "sha256-$hash" + ChecksumKind.sha512 -> "sha512-$hash" + } +} + +private fun artifactUrls( + coordinates: DependencyCoordinates, + metadata: ArtifactVerificationMetadata, + repository: Repository +): List { + val groupAsPath = coordinates.group.replace(".", "/") + + val attributes = mutableMapOf( + "organisation" to if (repository.m2Compatible) groupAsPath else coordinates.group, + "module" to coordinates.module, + "revision" to coordinates.version, + ) + fileAttributes(metadata.artifactName, coordinates.version) + + val resources = when (attributes["ext"]) { + "pom" -> if ("mavenPom" in repository.metadataSources) repository.metadataResources else repository.artifactResources + "xml" -> if ("ivyDescriptor" in repository.metadataSources) repository.metadataResources else repository.artifactResources + "module" -> if ("gradleMetadata" in repository.metadataSources || "ignoreGradleMetadataRedirection" !in repository.metadataSources) { + repository.metadataResources + } else { + repository.artifactResources + } + else -> repository.artifactResources + } + + val urls = mutableListOf() + + for (resource in resources) { + val location = attributes.entries.fold(fill(resource, attributes)) { acc, (key, value) -> + acc.replace("[$key]", value) + } + if (location.none { it == '[' || it == ']' }) { + urls.add(location) + } + } + + return urls +} + +private val optionalRegex = Regex("\\(([^)]+)\\)") +private val attrRegex = Regex("\\[([^]]+)]") + +private fun fill(template: String, attributes: Map): String { + return optionalRegex.replace(template) { match -> + attrRegex.find(match.value)?.groupValues?.get(1)?.let { attr -> + attributes[attr]?.takeIf { it.isNotBlank() }?.let { value -> + match.groupValues[1].replace("[$attr]", value) + } + } ?: "" + } +} + +// Gradle persists artifacts with the Maven artifact pattern, which may not match the repository's pattern. +private fun fileAttributes(file: String, version: String): Map { + val parts = Regex("(.+)-$version(-([^.]+))?(\\.(.+))?").matchEntire(file) ?: return emptyMap() + + val (artifact, _, classifier, _, ext) = parts.destructured + + return buildMap { + put("artifact", artifact) + put("classifier", classifier) + put("ext", ext) + } +} diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/Projects.kt b/app/src/main/kotlin/org/nixos/gradle2nix/Projects.kt index f112991..7beba7f 100644 --- a/app/src/main/kotlin/org/nixos/gradle2nix/Projects.kt +++ b/app/src/main/kotlin/org/nixos/gradle2nix/Projects.kt @@ -2,16 +2,5 @@ package org.nixos.gradle2nix import java.io.File -fun resolveProjects(config: Config) = config.allProjects.run { - if (config.buildSrc) { - flatMap { listOfNotNull(it, it.findBuildSrc()) } - } else { - this - } -} - -fun File.findBuildSrc(): File? = - resolve("buildSrc").takeIf { it.isDirectory } - fun File.isProjectRoot(): Boolean = isDirectory && (resolve("settings.gradle").isFile || resolve("settings.gradle.kts").isFile) diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ComponentArtifactIdentifier.kt b/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ComponentArtifactIdentifier.kt new file mode 100644 index 0000000..e4788ee --- /dev/null +++ b/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ComponentArtifactIdentifier.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nixos.gradle2nix.dependency + +/** + * An opaque immutable identifier for an artifact that belongs to some component instance. + */ +interface ComponentArtifactIdentifier { + /** + * Returns the id of the component that this artifact belongs to. + */ + val componentIdentifier: ComponentIdentifier + + /** + * Returns some human-consumable display name for this artifact. + */ + val displayName: String +} diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ComponentIdentifier.kt b/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ComponentIdentifier.kt new file mode 100644 index 0000000..83b0bfc --- /dev/null +++ b/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ComponentIdentifier.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nixos.gradle2nix.dependency + +/** + * An opaque immutable identifier for a component instance. There are various sub-interfaces that expose specific details about the identifier. + */ +interface ComponentIdentifier { + /** + * Returns a human-consumable display name for this identifier. + * + * @return Component identifier display name + */ + val displayName: String +} diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ModuleComponentArtifactIdentifier.kt b/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ModuleComponentArtifactIdentifier.kt new file mode 100644 index 0000000..298284a --- /dev/null +++ b/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ModuleComponentArtifactIdentifier.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nixos.gradle2nix.dependency + +/** + * An immutable identifier for an artifact that belongs to some module version. + */ +interface ModuleComponentArtifactIdentifier : ComponentArtifactIdentifier { + /** + * Returns the id of the component that this artifact belongs to. + */ + override val componentIdentifier: ModuleComponentIdentifier + + /** + * Returns a file base name that can be used for this artifact. + */ + val fileName: String +} + +data class DefaultModuleComponentArtifactIdentifier( + override val componentIdentifier: ModuleComponentIdentifier, + override val fileName: String, +) : ModuleComponentArtifactIdentifier { + override val displayName: String get() = "$fileName ($componentIdentifier)" + + override fun toString(): String = displayName +} diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ModuleComponentIdentifier.kt b/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ModuleComponentIdentifier.kt new file mode 100644 index 0000000..8be353b --- /dev/null +++ b/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ModuleComponentIdentifier.kt @@ -0,0 +1,76 @@ +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nixos.gradle2nix.dependency + +/** + * An identifier for a component instance which is available as a module version. + */ +interface ModuleComponentIdentifier : ComponentIdentifier { + /** + * The module group of the component. + * + * @return Component group + */ + val group: String + + /** + * The module name of the component. + * + * @return Component module + */ + val module: String + + /** + * The module version of the component. + * + * @return Component version + */ + val version: String + + /** + * The module identifier of the component. Returns the same information + * as [group] and [module]. + * + * @return the module identifier + */ + val moduleIdentifier: ModuleIdentifier +} + +data class DefaultModuleComponentIdentifier( + override val moduleIdentifier: ModuleIdentifier, + override val version: String, +) : ModuleComponentIdentifier { + override val group: String + get() = moduleIdentifier.group + + override val module: String + get() = moduleIdentifier.name + + override val displayName: String + get() = "$group:$module:$version" + + override fun toString(): String = displayName +} + + +fun ModuleComponentIdentifier( + group: String, + module: String, + version: String +): ModuleComponentIdentifier = DefaultModuleComponentIdentifier( + DefaultModuleIdentifier(group, module), + version +) diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ModuleIdentifier.kt b/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ModuleIdentifier.kt new file mode 100644 index 0000000..5457f3f --- /dev/null +++ b/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ModuleIdentifier.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nixos.gradle2nix.dependency + +/** + * The identifier of a module. + */ +interface ModuleIdentifier { + /** + * The group of the module. + * + * @return module group + */ + val group: String + + /** + * The name of the module. + * + * @return module name + */ + val name: String +} + +data class DefaultModuleIdentifier( + override val group: String, + override val name: String, +) : ModuleIdentifier diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/ArtifactVerificationMetadata.kt b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/ArtifactVerificationMetadata.kt new file mode 100644 index 0000000..ae67531 --- /dev/null +++ b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/ArtifactVerificationMetadata.kt @@ -0,0 +1,6 @@ +package org.nixos.gradle2nix.metadata + +data class ArtifactVerificationMetadata( + val artifactName: String, + val checksums: List +) diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/Checksum.kt b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/Checksum.kt new file mode 100644 index 0000000..a5c84ef --- /dev/null +++ b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/Checksum.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nixos.gradle2nix.metadata + +/** + * Internal representation of a checksum, aimed at *verification*. + * A checksum consists of a kind (md5, sha1, ...), a value, but also + * provides *alternatives*. Alternatives are checksums which are + * deemed trusted, because sometimes in a single build we can see different + * checksums for the same module, because they are sourced from different + * repositories. + * + * In theory, this shouldn't be allowed. However, it's often the case that + * an artifact, in particular _metadata artifacts_ (POM files, ...) differ + * from one repository to the other (either by end of lines, additional line + * at the end of the file, ...). Because they are different doesn't mean that + * they are compromised, so this is a facility for the user to declare "I know + * I should use a single source of truth but the infrastructure is hard or + * impossible to fix so let's trust this source". + * + * In addition to the list of alternatives, a checksum also provides a source, + * which is documentation to explain where a checksum was found. + */ +data class Checksum( + val kind: ChecksumKind, + val value: String, + val alternatives: Set = emptySet(), + val origin: String? = null, + val reason: String? = null +) diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/ChecksumKind.kt b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/ChecksumKind.kt new file mode 100644 index 0000000..6469cf7 --- /dev/null +++ b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/ChecksumKind.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nixos.gradle2nix.metadata + +enum class ChecksumKind(val algorithm: String) { + md5("MD5"), + sha1("SHA1"), + sha256("SHA-256"), + sha512("SHA-512"); + + companion object { + private val SORTED_BY_SECURITY: List = listOf(sha512, sha256, sha1, md5) + fun mostSecureFirst(): List { + return SORTED_BY_SECURITY + } + } +} diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/ComponentVerificationMetadata.kt b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/ComponentVerificationMetadata.kt new file mode 100644 index 0000000..54e454c --- /dev/null +++ b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/ComponentVerificationMetadata.kt @@ -0,0 +1,8 @@ +package org.nixos.gradle2nix.metadata + +import org.nixos.gradle2nix.dependency.ModuleComponentIdentifier + +data class ComponentVerificationMetadata( + val componentId: ModuleComponentIdentifier, + val artifactVerifications: List, +) diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerificationConfiguration.kt b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerificationConfiguration.kt new file mode 100644 index 0000000..8bfbf18 --- /dev/null +++ b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerificationConfiguration.kt @@ -0,0 +1,98 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nixos.gradle2nix.metadata + +import org.nixos.gradle2nix.dependency.ModuleComponentArtifactIdentifier +import org.nixos.gradle2nix.dependency.ModuleComponentIdentifier + +class DependencyVerificationConfiguration( + val trustedArtifacts: List = emptyList(), +) { + data class TrustCoordinates internal constructor( + val group: String?, + val name: String?, + val version: String?, + val fileName: String?, + val isRegex: Boolean, + val reason: String? + ) : Comparable { + + fun matches(id: ModuleComponentArtifactIdentifier): Boolean { + val moduleComponentIdentifier: ModuleComponentIdentifier = id.componentIdentifier + return (matches(group, moduleComponentIdentifier.group) + && matches(name, moduleComponentIdentifier.module) + && matches(version, moduleComponentIdentifier.version) + && matches(fileName, id.fileName)) + } + + private fun matches(value: String?, expr: String): Boolean { + if (value == null) { + return true + } + return if (!isRegex) { + expr == value + } else expr.matches(value.toRegex()) + } + + override fun compareTo(other: TrustCoordinates): Int { + val regexComparison = isRegex.compareTo(other.isRegex) + if (regexComparison != 0) { + return regexComparison + } + val groupComparison = compareNullableStrings( + group, other.group + ) + if (groupComparison != 0) { + return groupComparison + } + val nameComparison = compareNullableStrings( + name, other.name + ) + if (nameComparison != 0) { + return nameComparison + } + val versionComparison = compareNullableStrings( + version, other.version + ) + if (versionComparison != 0) { + return versionComparison + } + val fileNameComparison = compareNullableStrings( + fileName, other.fileName + ) + return if (fileNameComparison != 0) { + fileNameComparison + } else compareNullableStrings( + reason, other.reason + ) + } + } + + companion object { + private fun compareNullableStrings(first: String?, second: String?): Int { + if (first == null) { + return if (second == null) { + 0 + } else { + -1 + } + } else if (second == null) { + return 1 + } + return first.compareTo(second) + } + } +} diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerificationXmlTags.kt b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerificationXmlTags.kt new file mode 100644 index 0000000..b6e019a --- /dev/null +++ b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerificationXmlTags.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nixos.gradle2nix.metadata + +internal object DependencyVerificationXmlTags { + const val ALSO_TRUST = "also-trust" + const val ARTIFACT = "artifact" + const val COMPONENT = "component" + const val COMPONENTS = "components" + const val CONFIG = "configuration" + const val ENABLED = "enabled" + const val FILE = "file" + const val GROUP = "group" + const val ID = "id" + const val IGNORED_KEY = "ignored-key" + const val IGNORED_KEYS = "ignored-keys" + const val KEY_SERVER = "key-server" + const val KEY_SERVERS = "key-servers" + const val NAME = "name" + const val ORIGIN = "origin" + const val PGP = "pgp" + const val REASON = "reason" + const val REGEX = "regex" + const val TRUST = "trust" + const val TRUSTED_ARTIFACTS = "trusted-artifacts" + const val TRUSTED_KEY = "trusted-key" + const val TRUSTED_KEYS = "trusted-keys" + const val TRUSTING = "trusting" + const val URI = "uri" + const val VALUE = "value" + const val VERIFICATION_METADATA = "verification-metadata" + const val VERIFY_METADATA = "verify-metadata" + const val VERIFY_SIGNATURES = "verify-signatures" + const val VERSION = "version" +} diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerificationsXmlReader.kt b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerificationsXmlReader.kt new file mode 100644 index 0000000..2976931 --- /dev/null +++ b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerificationsXmlReader.kt @@ -0,0 +1,421 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nixos.gradle2nix.metadata + +import java.io.IOException +import java.io.InputStream +import javax.xml.parsers.ParserConfigurationException +import javax.xml.parsers.SAXParser +import javax.xml.parsers.SAXParserFactory +import org.gradle.internal.UncheckedException +import org.nixos.gradle2nix.dependency.DefaultModuleComponentArtifactIdentifier +import org.nixos.gradle2nix.dependency.DefaultModuleComponentIdentifier +import org.nixos.gradle2nix.dependency.DefaultModuleIdentifier +import org.nixos.gradle2nix.dependency.ModuleComponentArtifactIdentifier +import org.nixos.gradle2nix.dependency.ModuleComponentIdentifier +import org.nixos.gradle2nix.dependency.ModuleIdentifier +import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.ALSO_TRUST +import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.ARTIFACT +import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.COMPONENT +import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.COMPONENTS +import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.CONFIG +import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.IGNORED_KEY +import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.IGNORED_KEYS +import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.KEY_SERVER +import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.KEY_SERVERS +import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.PGP +import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.TRUST +import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.TRUSTED_ARTIFACTS +import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.TRUSTED_KEY +import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.TRUSTED_KEYS +import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.TRUSTING +import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.VALUE +import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.VERIFICATION_METADATA +import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.VERIFY_METADATA +import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.VERIFY_SIGNATURES +import org.xml.sax.Attributes +import org.xml.sax.InputSource +import org.xml.sax.SAXException +import org.xml.sax.ext.DefaultHandler2 + +object DependencyVerificationsXmlReader { + fun readFromXml( + input: InputStream, + builder: DependencyVerifierBuilder + ) { + try { + val saxParser = createSecureParser() + val xmlReader = saxParser.xmlReader + val handler = VerifiersHandler(builder) + xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler", handler) + xmlReader.contentHandler = handler + xmlReader.parse(InputSource(input)) + } catch (e: Exception) { + throw IllegalStateException( + "Unable to read dependency verification metadata", + e + ) + } finally { + try { + input.close() + } catch (e: IOException) { + throw UncheckedException.throwAsUncheckedException(e) + } + } + } + + fun readFromXml(input: InputStream): DependencyVerifier { + val builder = DependencyVerifierBuilder() + readFromXml(input, builder) + return builder.build() + } + + @Throws(ParserConfigurationException::class, SAXException::class) + private fun createSecureParser(): SAXParser { + val spf = SAXParserFactory.newInstance() + spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false) + spf.setFeature("http://xml.org/sax/features/namespaces", false) + spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true) + return spf.newSAXParser() + } + + private class VerifiersHandler(private val builder: DependencyVerifierBuilder) : DefaultHandler2() { + private var inMetadata = false + private var inComponents = false + private var inConfiguration = false + private var inVerifyMetadata = false + private var inVerifySignatures = false + private var inTrustedArtifacts = false + private var inKeyServers = false + private var inIgnoredKeys = false + private var inTrustedKeys = false + private var inTrustedKey = false + private var currentTrustedKey: String? = null + private var currentComponent: ModuleComponentIdentifier? = null + private var currentArtifact: ModuleComponentArtifactIdentifier? = + null + private var currentChecksum: ChecksumKind? = null + + override fun startElement(uri: String, localName: String, qName: String, attributes: Attributes) { + when (qName) { + CONFIG -> inConfiguration = + true + + VERIFICATION_METADATA -> inMetadata = + true + + COMPONENTS -> { + assertInMetadata() + inComponents = true + } + + COMPONENT -> { + assertInComponents() + currentComponent = createComponentId(attributes) + } + + ARTIFACT -> { + assertValidComponent() + currentArtifact = createArtifactId(attributes) + } + + VERIFY_METADATA -> { + assertInConfiguration(VERIFY_METADATA) + inVerifyMetadata = true + } + + VERIFY_SIGNATURES -> { + assertInConfiguration(VERIFY_SIGNATURES) + inVerifySignatures = true + } + + TRUSTED_ARTIFACTS -> { + assertInConfiguration(TRUSTED_ARTIFACTS) + inTrustedArtifacts = true + } + + TRUSTED_KEY -> { + assertContext( + inTrustedKeys, + TRUSTED_KEY, + TRUSTED_KEYS + ) + inTrustedKey = true + } + + TRUSTED_KEYS -> { + assertInConfiguration(TRUSTED_KEYS) + inTrustedKeys = true + } + + TRUST -> { + assertInTrustedArtifacts() + addTrustedArtifact(attributes) + } + + TRUSTING -> { + assertContext( + inTrustedKey, + TRUSTING, + TRUSTED_KEY + ) + } + + KEY_SERVERS -> { + assertInConfiguration(KEY_SERVERS) + inKeyServers = true + } + + KEY_SERVER -> { + assertContext( + inKeyServers, + KEY_SERVER, + KEY_SERVERS + ) + } + + IGNORED_KEYS -> { + if (currentArtifact == null) { + assertInConfiguration(IGNORED_KEYS) + } + inIgnoredKeys = true + } + + IGNORED_KEY -> { + assertContext( + inIgnoredKeys, + IGNORED_KEY, + IGNORED_KEYS + ) + } + + else -> if (currentChecksum != null && ALSO_TRUST == qName) { + builder.addChecksum( + currentArtifact!!, + currentChecksum!!, + getAttribute(attributes, VALUE), + null, + null + ) + } else if (currentArtifact != null) { + if (PGP != qName) { + currentChecksum = enumValueOf(qName) + builder.addChecksum( + currentArtifact!!, + currentChecksum!!, + getAttribute( + attributes, + VALUE + ), + getNullableAttribute( + attributes, + DependencyVerificationXmlTags.ORIGIN + ), + getNullableAttribute( + attributes, + DependencyVerificationXmlTags.REASON + ) + ) + } + } + } + } + + private fun assertInTrustedArtifacts() { + assertContext( + inTrustedArtifacts, + TRUST, + TRUSTED_ARTIFACTS + ) + } + + private fun addTrustedArtifact(attributes: Attributes) { + var regex = false + val regexAttr = getNullableAttribute( + attributes, + DependencyVerificationXmlTags.REGEX + ) + if (regexAttr != null) { + regex = regexAttr.toBoolean() + } + builder.addTrustedArtifact( + getNullableAttribute( + attributes, + DependencyVerificationXmlTags.GROUP + ), + getNullableAttribute( + attributes, + DependencyVerificationXmlTags.NAME + ), + getNullableAttribute( + attributes, + DependencyVerificationXmlTags.VERSION + ), + getNullableAttribute( + attributes, + DependencyVerificationXmlTags.FILE + ), + regex, + getNullableAttribute( + attributes, + DependencyVerificationXmlTags.REASON + ) + ) + } + + private fun readBoolean(ch: CharArray, start: Int, length: Int): Boolean { + return String(ch, start, length).toBoolean() + } + + private fun assertInConfiguration(tag: String) { + assertContext( + inConfiguration, + tag, + DependencyVerificationXmlTags.CONFIG + ) + } + + private fun assertInComponents() { + assertContext( + inComponents, + DependencyVerificationXmlTags.COMPONENT, + DependencyVerificationXmlTags.COMPONENTS + ) + } + + private fun assertInMetadata() { + assertContext( + inMetadata, + DependencyVerificationXmlTags.COMPONENTS, + DependencyVerificationXmlTags.VERIFICATION_METADATA + ) + } + + private fun assertValidComponent() { + assertContext( + currentComponent != null, + ARTIFACT, + DependencyVerificationXmlTags.COMPONENT + ) + } + + override fun endElement(uri: String, localName: String, qName: String) { + when (qName) { + DependencyVerificationXmlTags.CONFIG -> inConfiguration = + false + + VERIFY_METADATA -> inVerifyMetadata = + false + + VERIFY_SIGNATURES -> inVerifySignatures = + false + + DependencyVerificationXmlTags.VERIFICATION_METADATA -> inMetadata = + false + + DependencyVerificationXmlTags.COMPONENTS -> inComponents = + false + + DependencyVerificationXmlTags.COMPONENT -> currentComponent = + null + + TRUSTED_ARTIFACTS -> inTrustedArtifacts = + false + + TRUSTED_KEYS -> inTrustedKeys = + false + + TRUSTED_KEY -> { + inTrustedKey = false + currentTrustedKey = null + } + + KEY_SERVERS -> inKeyServers = + false + + ARTIFACT -> { + currentArtifact = null + currentChecksum = null + } + + IGNORED_KEYS -> inIgnoredKeys = + false + } + } + + private fun createArtifactId(attributes: Attributes): ModuleComponentArtifactIdentifier { + return DefaultModuleComponentArtifactIdentifier( + currentComponent!!, + getAttribute( + attributes, + DependencyVerificationXmlTags.NAME + ) + ) + } + + private fun createComponentId(attributes: Attributes): ModuleComponentIdentifier { + return DefaultModuleComponentIdentifier( + createModuleId(attributes), + getAttribute( + attributes, + DependencyVerificationXmlTags.VERSION + ) + ) + } + + private fun createModuleId(attributes: Attributes): ModuleIdentifier { + return DefaultModuleIdentifier( + getAttribute( + attributes, + DependencyVerificationXmlTags.GROUP + ), + getAttribute( + attributes, + DependencyVerificationXmlTags.NAME + ) + ) + } + + private fun getAttribute(attributes: Attributes, name: String): String { + val value = attributes.getValue(name) + assertContext( + value != null, + "Missing attribute: $name" + ) + return value.intern() + } + + private fun getNullableAttribute(attributes: Attributes, name: String): String? { + val value = attributes.getValue(name) ?: return null + return value.intern() + } + + companion object { + private fun assertContext(test: Boolean, innerTag: String, outerTag: String) { + assertContext( + test, + "<$innerTag> must be found under the <$outerTag> tag" + ) + } + + private fun assertContext(test: Boolean, message: String) { + if (!test) { + throw IllegalStateException("Invalid dependency verification metadata file: $message") + } + } + } + } +} diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerifier.kt b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerifier.kt new file mode 100644 index 0000000..d2639c0 --- /dev/null +++ b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerifier.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nixos.gradle2nix.metadata + +import org.nixos.gradle2nix.dependency.ModuleComponentIdentifier + +class DependencyVerifier internal constructor( + val verificationMetadata: Map, + val configuration: DependencyVerificationConfiguration, +) diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerifierBuilder.kt b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerifierBuilder.kt new file mode 100644 index 0000000..2eeaa58 --- /dev/null +++ b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerifierBuilder.kt @@ -0,0 +1,162 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nixos.gradle2nix.metadata + +import org.nixos.gradle2nix.dependency.ModuleComponentArtifactIdentifier +import org.nixos.gradle2nix.dependency.ModuleComponentIdentifier + +class DependencyVerifierBuilder { + private val byComponent: MutableMap = mutableMapOf() + private val trustedArtifacts: MutableList = mutableListOf() + + fun addChecksum( + artifact: ModuleComponentArtifactIdentifier, + kind: ChecksumKind, + value: String, + origin: String?, + reason: String? + ) { + val componentIdentifier: ModuleComponentIdentifier = artifact.componentIdentifier + byComponent.getOrPut(componentIdentifier) { + ComponentVerificationsBuilder(componentIdentifier) + }.addChecksum(artifact, kind, value, origin, reason) + } + + @JvmOverloads + fun addTrustedArtifact( + group: String?, + name: String?, + version: String?, + fileName: String?, + regex: Boolean, + reason: String? = null + ) { + validateUserInput(group, name, version, fileName) + trustedArtifacts.add(DependencyVerificationConfiguration.TrustCoordinates(group, name, version, fileName, regex, reason)) + } + + private fun validateUserInput( + group: String?, + name: String?, + version: String?, + fileName: String? + ) { + // because this can be called from parsing XML, we need to perform additional verification + if (group == null && name == null && version == null && fileName == null) { + throw IllegalStateException("A trusted artifact must have at least one of group, name, version or file name not null") + } + } + + fun build(): DependencyVerifier { + return DependencyVerifier( + byComponent + .toSortedMap( + compareBy { it.group } + .thenBy { it.module } + .thenBy { it.version } + ) + .mapValues { it.value.build() }, + DependencyVerificationConfiguration(trustedArtifacts), + ) + } + + private class ComponentVerificationsBuilder(private val component: ModuleComponentIdentifier) { + private val byArtifact: MutableMap = mutableMapOf() + + fun addChecksum( + artifact: ModuleComponentArtifactIdentifier, + kind: ChecksumKind, + value: String, + origin: String?, + reason: String? + ) { + byArtifact.computeIfAbsent(artifact.fileName) { ArtifactVerificationBuilder() } + .addChecksum(kind, value, origin, reason) + } + + fun build(): ComponentVerificationMetadata { + return ComponentVerificationMetadata( + component, + byArtifact + .map { ArtifactVerificationMetadata(it.key, it.value.buildChecksums()) } + .sortedBy { it.artifactName } + ) + } + } + + protected class ArtifactVerificationBuilder { + private val builder: MutableMap = mutableMapOf() + + fun addChecksum(kind: ChecksumKind, value: String, origin: String?, reason: String?) { + val builder = builder.getOrPut(kind) { + ChecksumBuilder(kind) + } + builder.addChecksum(value) + if (origin != null) { + builder.withOrigin(origin) + } + if (reason != null) { + builder.withReason(reason) + } + } + + fun buildChecksums(): List { + return builder.values + .map(ChecksumBuilder::build) + .sortedBy { it.kind } + } + } + + private class ChecksumBuilder(private val kind: ChecksumKind) { + private var value: String? = null + private var origin: String? = null + private var reason: String? = null + private var alternatives: MutableSet = mutableSetOf() + + /** + * Sets the origin, if not set already. This is + * mostly used for automatic generation of checksums + */ + fun withOrigin(origin: String?) { + this.origin = this.origin ?: origin + } + + /** + * Sets the reason, if not set already. + */ + fun withReason(reason: String?) { + this.reason = this.reason ?: reason + } + + fun addChecksum(checksum: String) { + if (value == null) { + value = checksum + } else if (value != checksum) { + alternatives.add(checksum) + } + } + + fun build(): Checksum { + return Checksum( + kind, + checkNotNull(value) { "Checksum is null" }, + alternatives, + origin, + reason + ) + } + } +} diff --git a/app/src/test/kotlin/org/nixos/gradle2nix/BuildSrcTest.kt b/app/src/test/kotlin/org/nixos/gradle2nix/BuildSrcTest.kt deleted file mode 100644 index cd82130..0000000 --- a/app/src/test/kotlin/org/nixos/gradle2nix/BuildSrcTest.kt +++ /dev/null @@ -1,19 +0,0 @@ -package org.nixos.gradle2nix - -import org.spekframework.spek2.Spek -import org.spekframework.spek2.style.specification.describe -import strikt.api.expectThat -import strikt.assertions.containsKey - -object BuildSrcTest : Spek({ - fixture("buildsrc/plugin-in-buildsrc/kotlin") - val fixture: Fixture by memoized() - - describe("project with plugin in buildSrc") { - fixture.run() - - it("should include buildSrc in gradle env", timeout = 0) { - expectThat(fixture.env()).containsKey("buildSrc") - } - } -}) \ No newline at end of file diff --git a/app/src/test/kotlin/org/nixos/gradle2nix/GoldenTest.kt b/app/src/test/kotlin/org/nixos/gradle2nix/GoldenTest.kt new file mode 100644 index 0000000..7beaf76 --- /dev/null +++ b/app/src/test/kotlin/org/nixos/gradle2nix/GoldenTest.kt @@ -0,0 +1,40 @@ +package org.nixos.gradle2nix + +import io.kotest.core.spec.style.FunSpec + +class GoldenTest : FunSpec({ + context("basic") { + golden("basic/basic-java-project") + golden("basic/basic-kotlin-project") + } + context("buildsrc") { + golden("buildsrc/plugin-in-buildsrc") + } + context("dependency") { + golden("dependency/classifier") + golden("dependency/maven-bom") + golden("dependency/snapshot") + golden("dependency/snapshot-dynamic") + golden("dependency/snapshot-redirect") + } + context("integration") { + golden("integration/settings-buildscript") + } + context("ivy") { + golden("ivy/basic") + } + context("plugin") { + golden("plugin/resolves-from-default-repo") + } + context("s3") { + golden("s3/maven") + golden("s3/maven-snapshot") + } + context("settings") { + golden("settings/buildscript") + golden("settings/dependency-resolution-management") + } + context("subprojects") { + golden("subprojects/multi-module") + } +}) diff --git a/app/src/test/kotlin/org/nixos/gradle2nix/TestUtil.kt b/app/src/test/kotlin/org/nixos/gradle2nix/TestUtil.kt index 99d620c..49b6b07 100644 --- a/app/src/test/kotlin/org/nixos/gradle2nix/TestUtil.kt +++ b/app/src/test/kotlin/org/nixos/gradle2nix/TestUtil.kt @@ -1,60 +1,126 @@ package org.nixos.gradle2nix -import com.squareup.moshi.Moshi -import com.squareup.moshi.Types -import okio.buffer -import okio.source -import org.spekframework.spek2.dsl.Root -import strikt.api.expectThat -import strikt.assertions.exists -import strikt.assertions.isNotNull -import strikt.assertions.toPath +import io.kotest.assertions.fail +import io.kotest.common.ExperimentalKotest +import io.kotest.common.KotestInternal +import io.kotest.core.names.TestName +import io.kotest.core.source.sourceRef +import io.kotest.core.spec.style.scopes.ContainerScope +import io.kotest.core.spec.style.scopes.RootScope +import io.kotest.core.test.NestedTest +import io.kotest.core.test.TestScope +import io.kotest.core.test.TestType +import io.kotest.extensions.system.withEnvironment +import io.kotest.matchers.equals.beEqual +import io.kotest.matchers.equals.shouldBeEqual +import io.kotest.matchers.file.shouldBeAFile +import io.kotest.matchers.paths.shouldBeAFile +import io.kotest.matchers.should +import java.io.File +import java.io.FileFilter import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths -import kotlin.io.path.ExperimentalPathApi import kotlin.io.path.createTempDirectory +import kotlin.io.path.inputStream +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.SerializationException +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.decodeFromStream +import kotlinx.serialization.json.encodeToStream +import okio.use -private val moshi = Moshi.Builder().build() +private val app = Gradle2Nix() -class Fixture(val project: Path) { - private val app = Main() +@OptIn(ExperimentalSerializationApi::class) +private val json = Json { + prettyPrint = true + prettyPrintIndent = " " +} - fun run(vararg args: String) { - app.main(args.toList() + project.toString()) +@OptIn(ExperimentalKotest::class, ExperimentalSerializationApi::class, KotestInternal::class) +suspend fun TestScope.fixture( + project: String, + vararg args: String, + test: suspend TestScope.(Map>) -> Unit +) { + val tmp = Paths.get("build/tmp/gradle2nix").apply { toFile().mkdirs() } + val baseDir = Paths.get("../fixtures", project).toFile() + val children = baseDir.listFiles(FileFilter { it.isDirectory && (it.name == "groovy" || it.name == "kotlin") }) + ?.toList() + val cases = if (children.isNullOrEmpty()) { + listOf(project to baseDir) + } else { + children.map { "$project.${it.name}" to it } } + for (case in cases) { + registerTestCase( + NestedTest( + name = TestName(case.first), + disabled = false, + config = null, + type = TestType.Dynamic, + source = sourceRef() + ) { + var dirName = case.second.toString().replace("/", ".") + while (dirName.startsWith(".")) dirName = dirName.removePrefix(".") + while (dirName.endsWith(".")) dirName = dirName.removeSuffix(".") - fun env(): Map { - val file = (app.outDir ?: project.toFile()).resolve("${app.envFile}.json") - expectThat(file).toPath().exists() - val env = file.source().buffer().use { source -> - moshi - .adapter>( - Types.newParameterizedType(Map::class.java, String::class.java, NixGradleEnv::class.java) - ).fromJson(source) - } - expectThat(env).isNotNull() - return env!! + val tempDir = File(tmp.toFile(), dirName) + tempDir.deleteRecursively() + case.second.copyRecursively(tempDir) + + if (!tempDir.resolve("settings.gradle").exists() && !tempDir.resolve("settings.gradle.kts").exists()) { + Files.createFile(tempDir.resolve("settings.gradle").toPath()) + } + app.main(listOf("-d", tempDir.toString()) + args.withM2()) + val file = tempDir.resolve("${app.envFile}.json") + file.shouldBeAFile() + val env: Map> = file.inputStream().buffered().use { input -> + Json.decodeFromStream(input) + } + test(env) + } + ) } } -@OptIn(ExperimentalPathApi::class) -fun Root.fixture(name: String) { - val fixture by memoized( - factory = { - val url = checkNotNull(Thread.currentThread().contextClassLoader.getResource(name)?.toURI()) { - "$name: No test fixture found" +val updateGolden = System.getProperty("org.nixos.gradle2nix.update-golden") != null + +@OptIn(ExperimentalSerializationApi::class) +suspend fun TestScope.golden( + project: String, + vararg args: String, +) { + fixture(project, *args) { env -> + val filename = "${testCase.name.testName}.json" + val goldenFile = File("../fixtures/golden/$filename") + if (updateGolden) { + goldenFile.parentFile.mkdirs() + goldenFile.outputStream().buffered().use { output -> + json.encodeToStream(env, output) } - val fixtureRoot = Paths.get(url) - val dest = createTempDirectory("gradle2nix") - val src = checkNotNull(fixtureRoot.takeIf { Files.exists(it) }) { - "$name: Test fixture not found: $fixtureRoot" + } else { + if (!goldenFile.exists()) { + fail("Golden file '$filename' doesn't exist. Run with --update-golden to generate.") } - src.toFile().copyRecursively(dest.toFile()) - Fixture(dest) - }, - destructor = { - it.project.toFile().deleteRecursively() + val goldenData: Map> = try { + goldenFile.inputStream().buffered().use { input -> + json.decodeFromStream(input) + } + } catch (e: SerializationException) { + fail("Failed to load golden data from '$filename'. Run with --update-golden to regenerate.") + } + env should beEqual(goldenData) } - ) -} \ No newline at end of file + } +} + +val m2 = System.getProperty("org.nixos.gradle2nix.m2") + +private fun Array.withM2(): List { + val args = toMutableList() + if (args.indexOf("--") < 0) args.add("--") + args.add("-Dorg.nixos.gradle2nix.m2=$m2") + return args +} diff --git a/assets/gradle2nix.svg b/assets/gradle2nix.svg index 0569dea..4a642c4 100644 --- a/assets/gradle2nix.svg +++ b/assets/gradle2nix.svg @@ -2,21 +2,20 @@ + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="1280" + height="640" + viewBox="0 0 338.66666 169.33334" + version="1.1" + id="svg8" + inkscape:version="0.92.4 (5da689c313, 2019-01-14)" + sodipodi:docname="gradle2nix.svg"> { - this@allprojects.withConvention(JavaPluginConvention::class) { - sourceSets.all { - configurations { - named(compileClasspathConfigurationName) { - resolutionStrategy.activateDependencyLocking() - } - named(runtimeClasspathConfigurationName) { - resolutionStrategy.activateDependencyLocking() - } - } - } - - tasks.register("lock") { - doFirst { - assert(gradle.startParameter.isWriteDependencyLocks) - file("buildscript-gradle.lockfile").delete() - file("gradle.lockfile").delete() - } - doLast { - configurations.matching { it.isCanBeResolved }.all { resolve() } - } - } - } - } -} - tasks { wrapper { - gradleVersion = "6.8.1" + gradleVersion = "8.3" distributionType = Wrapper.DistributionType.ALL } } diff --git a/fixtures/basic/basic-java-project/groovy/build.gradle b/fixtures/basic/basic-java-project/groovy/build.gradle index e0f793a..b3fef8a 100644 --- a/fixtures/basic/basic-java-project/groovy/build.gradle +++ b/fixtures/basic/basic-java-project/groovy/build.gradle @@ -3,7 +3,6 @@ plugins { } repositories { - jcenter() mavenCentral() } diff --git a/fixtures/subprojects/dependent-subprojects/groovy/child-a/build.gradle b/fixtures/basic/basic-java-project/groovy/settings.gradle similarity index 100% rename from fixtures/subprojects/dependent-subprojects/groovy/child-a/build.gradle rename to fixtures/basic/basic-java-project/groovy/settings.gradle diff --git a/fixtures/basic/basic-java-project/kotlin/build.gradle.kts b/fixtures/basic/basic-java-project/kotlin/build.gradle.kts index 59670f1..02b6753 100644 --- a/fixtures/basic/basic-java-project/kotlin/build.gradle.kts +++ b/fixtures/basic/basic-java-project/kotlin/build.gradle.kts @@ -3,7 +3,6 @@ plugins { } repositories { - jcenter() mavenCentral() } diff --git a/fixtures/subprojects/dependent-subprojects/groovy/child-b/build.gradle b/fixtures/basic/basic-java-project/kotlin/settings.gradle.kts similarity index 100% rename from fixtures/subprojects/dependent-subprojects/groovy/child-b/build.gradle rename to fixtures/basic/basic-java-project/kotlin/settings.gradle.kts diff --git a/fixtures/basic/basic-kotlin-project/kotlin/build.gradle.kts b/fixtures/basic/basic-kotlin-project/kotlin/build.gradle.kts index c776334..d47e7c4 100644 --- a/fixtures/basic/basic-kotlin-project/kotlin/build.gradle.kts +++ b/fixtures/basic/basic-kotlin-project/kotlin/build.gradle.kts @@ -1,30 +1,30 @@ - val kotlinVersion = "1.3.61" - val spekVersion = "2.0.9" +val kotlinVersion = "1.6.21" +val spekVersion = "2.0.9" - plugins { - application - kotlin("jvm") version "1.3.61" - } +plugins { + application + kotlin("jvm") version "1.6.21" +} - dependencies { - compile(kotlin("stdlib")) - implementation("com.natpryce:konfig:1.6.10.0") - implementation("com.github.pengrad:java-telegram-bot-api:4.6.0") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3") - implementation("org.jetbrains.exposed:exposed-core:0.21.1") - implementation("org.jetbrains.exposed", "exposed-dao", "0.21.1") - implementation("org.jetbrains.exposed", "exposed-jdbc", "0.21.1") - implementation("org.jetbrains.exposed", "exposed-jodatime", "0.21.1") - implementation("io.javalin:javalin:3.7.0") - implementation("org.slf4j:slf4j-simple:1.8.0-beta4") - implementation(group = "org.xerial", name = "sqlite-jdbc", version = "3.30.1") - implementation("org.postgresql:postgresql:42.2.2") - implementation("com.fasterxml.jackson.core:jackson-databind:2.10.1") - testImplementation("org.spekframework.spek2:spek-dsl-jvm:$spekVersion") - testRuntimeOnly("org.spekframework.spek2:spek-runner-junit5:$spekVersion") - testCompile("com.winterbe:expekt:0.5.0") - } +dependencies { + compileOnly(kotlin("stdlib")) + implementation("com.natpryce:konfig:1.6.10.0") + implementation("com.github.pengrad:java-telegram-bot-api:4.6.0") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3") + implementation("org.jetbrains.exposed:exposed-core:0.21.1") + implementation("org.jetbrains.exposed", "exposed-dao", "0.21.1") + implementation("org.jetbrains.exposed", "exposed-jdbc", "0.21.1") + implementation("org.jetbrains.exposed", "exposed-jodatime", "0.21.1") + implementation("io.javalin:javalin:3.7.0") + implementation("org.slf4j:slf4j-simple:1.8.0-beta4") + implementation(group = "org.xerial", name = "sqlite-jdbc", version = "3.30.1") + implementation("org.postgresql:postgresql:42.2.2") + implementation("com.fasterxml.jackson.core:jackson-databind:2.10.1") + testImplementation("org.spekframework.spek2:spek-dsl-jvm:$spekVersion") + testRuntimeOnly("org.spekframework.spek2:spek-runner-junit5:$spekVersion") + testCompileOnly("com.winterbe:expekt:0.5.0") +} - repositories { - jcenter() - } +repositories { + mavenCentral() +} diff --git a/fixtures/subprojects/dependent-subprojects/groovy/child-c/build.gradle b/fixtures/basic/basic-kotlin-project/kotlin/settings.gradle.kts similarity index 100% rename from fixtures/subprojects/dependent-subprojects/groovy/child-c/build.gradle rename to fixtures/basic/basic-kotlin-project/kotlin/settings.gradle.kts diff --git a/fixtures/buildsrc/plugin-in-buildsrc/kotlin/build.gradle.kts b/fixtures/buildsrc/plugin-in-buildsrc/kotlin/build.gradle.kts index 62f05d4..c9641cd 100644 --- a/fixtures/buildsrc/plugin-in-buildsrc/kotlin/build.gradle.kts +++ b/fixtures/buildsrc/plugin-in-buildsrc/kotlin/build.gradle.kts @@ -1,4 +1,4 @@ plugins { `java-library` - id("com.example.custom-spotless") -} \ No newline at end of file + id("com.example.apply-plugin-publish") +} diff --git a/fixtures/buildsrc/plugin-in-buildsrc/kotlin/buildSrc/build.gradle.kts b/fixtures/buildsrc/plugin-in-buildsrc/kotlin/buildSrc/build.gradle.kts index cbd39da..a77804b 100644 --- a/fixtures/buildsrc/plugin-in-buildsrc/kotlin/buildSrc/build.gradle.kts +++ b/fixtures/buildsrc/plugin-in-buildsrc/kotlin/buildSrc/build.gradle.kts @@ -3,10 +3,9 @@ plugins { } repositories { - jcenter() gradlePluginPortal() } dependencies { - implementation("com.diffplug.spotless:spotless-plugin-gradle:3.28.1") + implementation("com.gradle.publish:plugin-publish-plugin:1.2.1") } diff --git a/fixtures/buildsrc/plugin-in-buildsrc/kotlin/buildSrc/src/main/kotlin/com.example/apply-plugin-publish.gradle.kts b/fixtures/buildsrc/plugin-in-buildsrc/kotlin/buildSrc/src/main/kotlin/com.example/apply-plugin-publish.gradle.kts new file mode 100644 index 0000000..7c0993e --- /dev/null +++ b/fixtures/buildsrc/plugin-in-buildsrc/kotlin/buildSrc/src/main/kotlin/com.example/apply-plugin-publish.gradle.kts @@ -0,0 +1,5 @@ +package com.example + +plugins { + id("com.gradle.plugin-publish") +} diff --git a/fixtures/buildsrc/plugin-in-buildsrc/kotlin/buildSrc/src/main/kotlin/com.example/custom-spotless.gradle.kts b/fixtures/buildsrc/plugin-in-buildsrc/kotlin/buildSrc/src/main/kotlin/com.example/custom-spotless.gradle.kts deleted file mode 100644 index 518ad01..0000000 --- a/fixtures/buildsrc/plugin-in-buildsrc/kotlin/buildSrc/src/main/kotlin/com.example/custom-spotless.gradle.kts +++ /dev/null @@ -1,11 +0,0 @@ -package com.example - -plugins { - com.diffplug.gradle.spotless -} - -spotless { - kotlin { - ktlint() - } -} \ No newline at end of file diff --git a/fixtures/subprojects/dependent-subprojects/groovy/child-d/build.gradle b/fixtures/dependency/classifier/groovy/settings.gradle similarity index 100% rename from fixtures/subprojects/dependent-subprojects/groovy/child-d/build.gradle rename to fixtures/dependency/classifier/groovy/settings.gradle diff --git a/fixtures/dependency/classifier/kotlin/build.gradle.kts b/fixtures/dependency/classifier/kotlin/build.gradle.kts index e195487..524aa43 100644 --- a/fixtures/dependency/classifier/kotlin/build.gradle.kts +++ b/fixtures/dependency/classifier/kotlin/build.gradle.kts @@ -8,4 +8,4 @@ repositories { dependencies { implementation("com.badlogicgames.gdx:gdx-platform:1.9.9:natives-desktop") -} \ No newline at end of file +} diff --git a/fixtures/dependency/classifier/kotlin/settings.gradle.kts b/fixtures/dependency/classifier/kotlin/settings.gradle.kts new file mode 100644 index 0000000..e69de29 diff --git a/fixtures/dependency/maven-bom/kotlin/build.gradle.kts b/fixtures/dependency/maven-bom/kotlin/build.gradle.kts index 9ad9517..2734242 100644 --- a/fixtures/dependency/maven-bom/kotlin/build.gradle.kts +++ b/fixtures/dependency/maven-bom/kotlin/build.gradle.kts @@ -3,10 +3,10 @@ plugins { } repositories { - maven { url = uri("http://localhost:9999") } + maven { url = uri(System.getProperty("org.nixos.gradle2nix.m2")) } } dependencies { implementation(platform("io.micrometer:micrometer-bom:1.5.1")) implementation("io.micrometer:micrometer-core") -} \ No newline at end of file +} diff --git a/fixtures/dependency/maven-bom/kotlin/settings.gradle.kts b/fixtures/dependency/maven-bom/kotlin/settings.gradle.kts new file mode 100644 index 0000000..e69de29 diff --git a/fixtures/dependency/snapshot-dynamic/groovy/build.gradle b/fixtures/dependency/snapshot-dynamic/groovy/build.gradle index 5b137e1..83d134f 100644 --- a/fixtures/dependency/snapshot-dynamic/groovy/build.gradle +++ b/fixtures/dependency/snapshot-dynamic/groovy/build.gradle @@ -3,9 +3,9 @@ plugins { } repositories { - maven { url = uri("http://localhost:9999") } + maven { url = uri(System.getProperty("org.nixos.gradle2nix.m2")) } } dependencies { implementation "org.apache:test-SNAPSHOT1:2.0.2-SNAPSHOT" -} \ No newline at end of file +} diff --git a/fixtures/dependency/snapshot-dynamic/groovy/settings.gradle b/fixtures/dependency/snapshot-dynamic/groovy/settings.gradle new file mode 100644 index 0000000..e69de29 diff --git a/fixtures/dependency/snapshot-dynamic/kotlin/build.gradle.kts b/fixtures/dependency/snapshot-dynamic/kotlin/build.gradle.kts index 805f99e..695191a 100644 --- a/fixtures/dependency/snapshot-dynamic/kotlin/build.gradle.kts +++ b/fixtures/dependency/snapshot-dynamic/kotlin/build.gradle.kts @@ -1,9 +1,10 @@ + plugins { java } repositories { - maven { url = uri("http://localhost:9999") } + maven { url = uri(System.getProperty("org.nixos.gradle2nix.m2")) } } dependencies { diff --git a/fixtures/dependency/snapshot-dynamic/kotlin/settings.gradle.kts b/fixtures/dependency/snapshot-dynamic/kotlin/settings.gradle.kts new file mode 100644 index 0000000..e69de29 diff --git a/fixtures/dependency/snapshot-redirect/groovy/build.gradle b/fixtures/dependency/snapshot-redirect/groovy/build.gradle index a2a9953..70cfd52 100644 --- a/fixtures/dependency/snapshot-redirect/groovy/build.gradle +++ b/fixtures/dependency/snapshot-redirect/groovy/build.gradle @@ -3,10 +3,9 @@ plugins { } repositories { - jcenter() maven { url 'https://jitpack.io' } } dependencies { implementation 'com.github.anuken:packr:-SNAPSHOT' -} \ No newline at end of file +} diff --git a/fixtures/dependency/snapshot-redirect/groovy/settings.gradle b/fixtures/dependency/snapshot-redirect/groovy/settings.gradle new file mode 100644 index 0000000..e69de29 diff --git a/fixtures/dependency/snapshot/groovy/build.gradle b/fixtures/dependency/snapshot/groovy/build.gradle index e0a1b63..a752a63 100644 --- a/fixtures/dependency/snapshot/groovy/build.gradle +++ b/fixtures/dependency/snapshot/groovy/build.gradle @@ -3,9 +3,9 @@ plugins { } repositories { - maven { url = uri("http://localhost:9999") } + maven { url = uri("file:/../../../../") } } dependencies { implementation "org.apache:test-SNAPSHOT2:2.0.2-SNAPSHOT" -} \ No newline at end of file +} diff --git a/fixtures/dependency/snapshot/groovy/settings.gradle b/fixtures/dependency/snapshot/groovy/settings.gradle new file mode 100644 index 0000000..e69de29 diff --git a/fixtures/dependency/snapshot/kotlin/build.gradle.kts b/fixtures/dependency/snapshot/kotlin/build.gradle.kts index ed66d2a..5fdce81 100644 --- a/fixtures/dependency/snapshot/kotlin/build.gradle.kts +++ b/fixtures/dependency/snapshot/kotlin/build.gradle.kts @@ -1,9 +1,10 @@ + plugins { java } repositories { - maven { url = uri("http://localhost:9999") } + maven { url = uri(System.getProperty("org.nixos.gradle2nix.m2")) } } dependencies { diff --git a/fixtures/dependency/snapshot/kotlin/settings.gradle.kts b/fixtures/dependency/snapshot/kotlin/settings.gradle.kts new file mode 100644 index 0000000..e69de29 diff --git a/fixtures/golden/basic/basic-java-project.groovy.json b/fixtures/golden/basic/basic-java-project.groovy.json new file mode 100644 index 0000000..83d14c1 --- /dev/null +++ b/fixtures/golden/basic/basic-java-project.groovy.json @@ -0,0 +1,72 @@ +{ + "com.squareup.okio:okio:2.2.2": { + "okio-2.2.2.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/2.2.2/okio-2.2.2.jar" + ], + "hash": "sha256-5YyXQGprsROIk3UCmaxjxqoEs4trSerhv8rRpj75uhs=" + }, + "okio-2.2.2.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/2.2.2/okio-2.2.2.pom" + ], + "hash": "sha256-/WIZiPf2lXAlc13G3QkLAKIPOju413ynkDYHf2KbFAs=" + } + }, + "com.squareup.moshi:moshi:1.8.0": { + "moshi-1.8.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/moshi/moshi/1.8.0/moshi-1.8.0.jar" + ], + "hash": "sha256-Qv50bSaU6hH+agK+zZ2iyj2v6Xye/VCg+a9cRZbnSmo=" + }, + "moshi-1.8.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/moshi/moshi/1.8.0/moshi-1.8.0.pom" + ], + "hash": "sha256-FLuAWbnddiACWSkN+IfjfmaaB0qsnImUAePIEC/lII8=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib:1.2.60": { + "kotlin-stdlib-1.2.60.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.2.60/kotlin-stdlib-1.2.60.jar" + ], + "hash": "sha256-ahMCmPUXGsUqHiSW9+rnhbb1ZBbqPMuZ5DRNBNg/8HE=" + }, + "kotlin-stdlib-1.2.60.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.2.60/kotlin-stdlib-1.2.60.pom" + ], + "hash": "sha256-5jKJkgnmtMqrlA/YLk7GOjLjJkP4Fff6cJdkeJDXnxg=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib-common:1.2.60": { + "kotlin-stdlib-common-1.2.60.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.2.60/kotlin-stdlib-common-1.2.60.jar" + ], + "hash": "sha256-CbQ3WgZc8SeryZjF3PIrFmTEWvQrSJSZ16j0+Kt5P7E=" + }, + "kotlin-stdlib-common-1.2.60.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.2.60/kotlin-stdlib-common-1.2.60.pom" + ], + "hash": "sha256-gwwnrx4c8k8PUm6kV5AcQ/OMGbtvfl03Y8PSU98bjaE=" + } + }, + "org.jetbrains:annotations:13.0": { + "annotations-13.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/annotations/13.0/annotations-13.0.jar" + ], + "hash": "sha256-rOKhDcji1f00kl7KwD5JiLLA+FFlDJS4zvSbob0RFHg=" + }, + "annotations-13.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/annotations/13.0/annotations-13.0.pom" + ], + "hash": "sha256-llrrK+3/NpgZvd4b96CzuJuCR91pyIuGN112Fju4w5c=" + } + } +} \ No newline at end of file diff --git a/fixtures/golden/basic/basic-java-project.kotlin.json b/fixtures/golden/basic/basic-java-project.kotlin.json new file mode 100644 index 0000000..83d14c1 --- /dev/null +++ b/fixtures/golden/basic/basic-java-project.kotlin.json @@ -0,0 +1,72 @@ +{ + "com.squareup.okio:okio:2.2.2": { + "okio-2.2.2.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/2.2.2/okio-2.2.2.jar" + ], + "hash": "sha256-5YyXQGprsROIk3UCmaxjxqoEs4trSerhv8rRpj75uhs=" + }, + "okio-2.2.2.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/2.2.2/okio-2.2.2.pom" + ], + "hash": "sha256-/WIZiPf2lXAlc13G3QkLAKIPOju413ynkDYHf2KbFAs=" + } + }, + "com.squareup.moshi:moshi:1.8.0": { + "moshi-1.8.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/moshi/moshi/1.8.0/moshi-1.8.0.jar" + ], + "hash": "sha256-Qv50bSaU6hH+agK+zZ2iyj2v6Xye/VCg+a9cRZbnSmo=" + }, + "moshi-1.8.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/moshi/moshi/1.8.0/moshi-1.8.0.pom" + ], + "hash": "sha256-FLuAWbnddiACWSkN+IfjfmaaB0qsnImUAePIEC/lII8=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib:1.2.60": { + "kotlin-stdlib-1.2.60.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.2.60/kotlin-stdlib-1.2.60.jar" + ], + "hash": "sha256-ahMCmPUXGsUqHiSW9+rnhbb1ZBbqPMuZ5DRNBNg/8HE=" + }, + "kotlin-stdlib-1.2.60.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.2.60/kotlin-stdlib-1.2.60.pom" + ], + "hash": "sha256-5jKJkgnmtMqrlA/YLk7GOjLjJkP4Fff6cJdkeJDXnxg=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib-common:1.2.60": { + "kotlin-stdlib-common-1.2.60.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.2.60/kotlin-stdlib-common-1.2.60.jar" + ], + "hash": "sha256-CbQ3WgZc8SeryZjF3PIrFmTEWvQrSJSZ16j0+Kt5P7E=" + }, + "kotlin-stdlib-common-1.2.60.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.2.60/kotlin-stdlib-common-1.2.60.pom" + ], + "hash": "sha256-gwwnrx4c8k8PUm6kV5AcQ/OMGbtvfl03Y8PSU98bjaE=" + } + }, + "org.jetbrains:annotations:13.0": { + "annotations-13.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/annotations/13.0/annotations-13.0.jar" + ], + "hash": "sha256-rOKhDcji1f00kl7KwD5JiLLA+FFlDJS4zvSbob0RFHg=" + }, + "annotations-13.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/annotations/13.0/annotations-13.0.pom" + ], + "hash": "sha256-llrrK+3/NpgZvd4b96CzuJuCR91pyIuGN112Fju4w5c=" + } + } +} \ No newline at end of file diff --git a/fixtures/golden/basic/basic-kotlin-project.kotlin.json b/fixtures/golden/basic/basic-kotlin-project.kotlin.json new file mode 100644 index 0000000..cf9a936 --- /dev/null +++ b/fixtures/golden/basic/basic-kotlin-project.kotlin.json @@ -0,0 +1,1258 @@ +{ + "org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.6.21": { + "org.jetbrains.kotlin.jvm.gradle.plugin-1.6.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.6.21/org.jetbrains.kotlin.jvm.gradle.plugin-1.6.21.pom" + ], + "hash": "sha256-hKJnm90W1DkKJmp58Gzaix+iq38XlowYk0l84ZWOHEQ=" + } + }, + "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21": { + "kotlin-gradle-plugin-1.6.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin/1.6.21/kotlin-gradle-plugin-1.6.21.jar" + ], + "hash": "sha256-Z1Oi4RJtP5k6lRryrcBrHsTKJxdulsj2Mnd5kBBNFa0=" + }, + "kotlin-gradle-plugin-1.6.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin/1.6.21/kotlin-gradle-plugin-1.6.21.pom" + ], + "hash": "sha256-7RX0N/j1aW6NU7mszIYS6cas9Wfbau0E/ymq3F4DpC4=" + } + }, + "org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.6.21": { + "kotlin-gradle-plugin-api-1.6.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.6.21/kotlin-gradle-plugin-api-1.6.21.jar" + ], + "hash": "sha256-x0wfF5FsrG1ygGJkmI0V4yGa8kYJB5E3Tq6cua8ufLM=" + }, + "kotlin-gradle-plugin-api-1.6.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.6.21/kotlin-gradle-plugin-api-1.6.21.pom" + ], + "hash": "sha256-JL0R1cjnNGMHSBUXnPuyYCAJIxyEE5aTr3ydVtzU3z8=" + } + }, + "org.jetbrains.kotlin:kotlin-native-utils:1.6.21": { + "kotlin-native-utils-1.6.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-native-utils/1.6.21/kotlin-native-utils-1.6.21.jar" + ], + "hash": "sha256-a9hyJOVq4V/+IQTTx2M9cq9sezWCRa08SnbG1f0NNr8=" + }, + "kotlin-native-utils-1.6.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-native-utils/1.6.21/kotlin-native-utils-1.6.21.pom" + ], + "hash": "sha256-92q9t+TzvxouyTxiqybO/lKg7UlBAY53w/74BrCXvq8=" + } + }, + "org.jetbrains.kotlin:kotlin-util-io:1.6.21": { + "kotlin-util-io-1.6.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-io/1.6.21/kotlin-util-io-1.6.21.jar" + ], + "hash": "sha256-wCxUcFYyGLcDvh5xbi0M6leH01y+tryUbfAMAM1CrNI=" + }, + "kotlin-util-io-1.6.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-io/1.6.21/kotlin-util-io-1.6.21.pom" + ], + "hash": "sha256-52nyybmRQIYlhKLAoRLIQ3P0fkryrxbQHOSThRMZMhk=" + } + }, + "org.jetbrains.kotlin:kotlin-project-model:1.6.21": { + "kotlin-project-model-1.6.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-project-model/1.6.21/kotlin-project-model-1.6.21.jar" + ], + "hash": "sha256-FLaE+Kc+IpZ4ASS/OB3eAT9YLqIzZ6zgGEWAo4Sa6Ng=" + }, + "kotlin-project-model-1.6.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-project-model/1.6.21/kotlin-project-model-1.6.21.pom" + ], + "hash": "sha256-dgKHUWgMZJAf76wyN5AmtNC9I3rdfw873ujtXH51LG4=" + } + }, + "org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.6.21": { + "kotlin-gradle-plugin-model-1.6.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.6.21/kotlin-gradle-plugin-model-1.6.21.jar" + ], + "hash": "sha256-YFmxxhMI+4WaAedYsrj9Ctr/dBs9+AI1+t6VrWq4loc=" + }, + "kotlin-gradle-plugin-model-1.6.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.6.21/kotlin-gradle-plugin-model-1.6.21.pom" + ], + "hash": "sha256-QkLJzsOQLX21n4OMupPDDnMeC10yzDnQ5Ft1gKZUBOo=" + } + }, + "org.jetbrains.kotlin:kotlin-util-klib:1.6.21": { + "kotlin-util-klib-1.6.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-klib/1.6.21/kotlin-util-klib-1.6.21.jar" + ], + "hash": "sha256-7iGKnoGAwbNIwawc+K1xj2qseLp+JrUIEyNIT2Q8YbI=" + }, + "kotlin-util-klib-1.6.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-klib/1.6.21/kotlin-util-klib-1.6.21.pom" + ], + "hash": "sha256-EsegqvZnLbHXgxxHGWV/+b9rEXGbD8h9iNcnXzl/lKs=" + } + }, + "org.jetbrains.kotlin:kotlin-klib-commonizer-api:1.6.21": { + "kotlin-klib-commonizer-api-1.6.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.6.21/kotlin-klib-commonizer-api-1.6.21.jar" + ], + "hash": "sha256-0s9pUu7ziUqs+KnYzx6MZ78hW075AmioyQMYNFMKOHQ=" + }, + "kotlin-klib-commonizer-api-1.6.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.6.21/kotlin-klib-commonizer-api-1.6.21.pom" + ], + "hash": "sha256-FICJ7qPCUPClDqxomfFFq5D1mJM8GrT5qsldYXKHJfQ=" + } + }, + "org.jetbrains.kotlin:kotlin-tooling-metadata:1.6.21": { + "kotlin-tooling-metadata-1.6.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-tooling-metadata/1.6.21/kotlin-tooling-metadata-1.6.21.jar" + ], + "hash": "sha256-Tsk9BRYGawtki6mHxtPWX2+wZ9wLu6lcHs5h4EKEiOU=" + }, + "kotlin-tooling-metadata-1.6.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-tooling-metadata/1.6.21/kotlin-tooling-metadata-1.6.21.pom" + ], + "hash": "sha256-uwYH34aI9gLBwvTQmWMz/YsDtpMoaGpud15S9/sNFxg=" + } + }, + "com.google.code.gson:gson:2.8.9": { + "gson-2.8.9.jar": { + "urls": [ + "https://plugins.gradle.org/m2/com/google/code/gson/gson/2.8.9/gson-2.8.9.jar" + ], + "hash": "sha256-05mSkYVd5JXJTHQ3YbirUXbP6r4oGlqw2OjUUyb9cD4=" + }, + "gson-2.8.9.pom": { + "urls": [ + "https://plugins.gradle.org/m2/com/google/code/gson/gson/2.8.9/gson-2.8.9.pom" + ], + "hash": "sha256-r97W5qaQ+/OtSuZa2jl/CpCl9jCzA9G3QbnJeSb91N4=" + } + }, + "com.google.guava:guava:29.0-jre": { + "guava-29.0-jre.jar": { + "urls": [ + "https://plugins.gradle.org/m2/com/google/guava/guava/29.0-jre/guava-29.0-jre.jar" + ], + "hash": "sha256-sixftm1h57lSJTHQSy+RW1FY6AqgtA7nKCyL+wew2iU=" + }, + "guava-29.0-jre.pom": { + "urls": [ + "https://plugins.gradle.org/m2/com/google/guava/guava/29.0-jre/guava-29.0-jre.pom" + ], + "hash": "sha256-kCfpNAmJA9KH8bphyLZfAdHR4dp6b7zAS/PeBUQBRCY=" + } + }, + "com.google.guava:failureaccess:1.0.1": { + "failureaccess-1.0.1.jar": { + "urls": [ + "https://plugins.gradle.org/m2/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar" + ], + "hash": "sha256-oXHuTHNN0tqDfksWvp30Zhr6typBra8x64Tf2vk2yiY=" + }, + "failureaccess-1.0.1.pom": { + "urls": [ + "https://plugins.gradle.org/m2/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.pom" + ], + "hash": "sha256-6WBCznj+y6DaK+lkUilHyHtAopG1/TzWcqQ0kkEDxLk=" + } + }, + "com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava": { + "listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar": { + "urls": [ + "https://plugins.gradle.org/m2/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar" + ], + "hash": "sha256-s3KgN9QjCqV/vv/e8w/WEj+cDC24XQrO0AyRuXTzP5k=" + }, + "listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.pom": { + "urls": [ + "https://plugins.gradle.org/m2/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.pom" + ], + "hash": "sha256-GNSx2yYVPU5VB5zh92ux/gXNuGLvmVSojLzE/zi4Z5s=" + } + }, + "com.google.code.findbugs:jsr305:3.0.2": { + "jsr305-3.0.2.jar": { + "urls": [ + "https://plugins.gradle.org/m2/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" + ], + "hash": "sha256-dmrSoHg/JoeWLIrXTO7MOKKLn3Ki0IXuQ4t4E+ko0Mc=" + }, + "jsr305-3.0.2.pom": { + "urls": [ + "https://plugins.gradle.org/m2/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.pom" + ], + "hash": "sha256-GYidvfGyVLJgGl7mRbgUepdGRIgil2hMeYr+XWPXjf4=" + } + }, + "org.checkerframework:checker-qual:2.11.1": { + "checker-qual-2.11.1.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/checkerframework/checker-qual/2.11.1/checker-qual-2.11.1.jar" + ], + "hash": "sha256-AVIkpLHcbebaBTJz1Np9Oc/qIOYwOBafxFrA0dycWTg=" + }, + "checker-qual-2.11.1.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/checkerframework/checker-qual/2.11.1/checker-qual-2.11.1.pom" + ], + "hash": "sha256-zy4MkNj3V0VfSiWOpglzkFNmO9XaannZvVP5NaR955w=" + } + }, + "com.google.errorprone:error_prone_annotations:2.3.4": { + "error_prone_annotations-2.3.4.jar": { + "urls": [ + "https://plugins.gradle.org/m2/com/google/errorprone/error_prone_annotations/2.3.4/error_prone_annotations-2.3.4.jar" + ], + "hash": "sha256-uvfW6pfOYGxT4RtoVLpfLOfvXCTd3wr6GNEmC9JbACw=" + }, + "error_prone_annotations-2.3.4.pom": { + "urls": [ + "https://plugins.gradle.org/m2/com/google/errorprone/error_prone_annotations/2.3.4/error_prone_annotations-2.3.4.pom" + ], + "hash": "sha256-EyZziktPfMrPYHuGahH7hRk+9g9qWUYRh85yZfm+W+0=" + } + }, + "com.google.j2objc:j2objc-annotations:1.3": { + "j2objc-annotations-1.3.jar": { + "urls": [ + "https://plugins.gradle.org/m2/com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3.jar" + ], + "hash": "sha256-Ia8wySJnvWEiwOC00gzMtmQaN+r5VsZUDsRx1YTmSns=" + }, + "j2objc-annotations-1.3.pom": { + "urls": [ + "https://plugins.gradle.org/m2/com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3.pom" + ], + "hash": "sha256-X6yoJLoRW+5FhzAzff2y/OpGui/XdNQwTtvzD6aj8FU=" + } + }, + "de.undercouch:gradle-download-task:4.1.1": { + "gradle-download-task-4.1.1.jar": { + "urls": [ + "https://plugins.gradle.org/m2/de/undercouch/gradle-download-task/4.1.1/gradle-download-task-4.1.1.jar" + ], + "hash": "sha256-6wi1cOQI1GRnBecKlJYU1DnqKxFFXxZSqwMw3olU2rk=" + }, + "gradle-download-task-4.1.1.pom": { + "urls": [ + "https://plugins.gradle.org/m2/de/undercouch/gradle-download-task/4.1.1/gradle-download-task-4.1.1.pom" + ], + "hash": "sha256-EQnx9xpUJU1ZAzfYudRD+d/AhyjJwdgzVlXMHcyIwLk=" + } + }, + "com.github.gundy:semver4j:0.16.4": { + "semver4j-0.16.4-nodeps.jar": { + "urls": [ + "https://plugins.gradle.org/m2/com/github/gundy/semver4j/0.16.4/semver4j-0.16.4-nodeps.jar" + ], + "hash": "sha256-P1nspRY3TM1P01UWJb9Q+KSxkfcAUI985IZkYKYSivA=" + }, + "semver4j-0.16.4.pom": { + "urls": [ + "https://plugins.gradle.org/m2/com/github/gundy/semver4j/0.16.4/semver4j-0.16.4.pom" + ], + "hash": "sha256-MgAdskQ7M53SH1t5/ynRreci0boIDCFL3oGfD3LRYE0=" + } + }, + "org.jetbrains.kotlin:kotlin-compiler-embeddable:1.6.21": { + "kotlin-compiler-embeddable-1.6.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.6.21/kotlin-compiler-embeddable-1.6.21.jar", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.6.21/kotlin-compiler-embeddable-1.6.21.jar" + ], + "hash": "sha256-X5ZQPNgiqmwg7abHFqVTxBTYAO0Mbn1lX6Gx+/1P7Cs=" + }, + "kotlin-compiler-embeddable-1.6.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.6.21/kotlin-compiler-embeddable-1.6.21.pom", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.6.21/kotlin-compiler-embeddable-1.6.21.pom" + ], + "hash": "sha256-wpULrWEPTie9iidbgcDoPIUfGD1gTuH7iRJV9DRa9EE=" + } + }, + "org.jetbrains.kotlin:kotlin-daemon-embeddable:1.6.21": { + "kotlin-daemon-embeddable-1.6.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.6.21/kotlin-daemon-embeddable-1.6.21.jar", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.6.21/kotlin-daemon-embeddable-1.6.21.jar" + ], + "hash": "sha256-UcPsHDLDbWVw2DFC6v4qJCk08WXwt4w4YTdpBfkPLhI=" + }, + "kotlin-daemon-embeddable-1.6.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.6.21/kotlin-daemon-embeddable-1.6.21.pom", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.6.21/kotlin-daemon-embeddable-1.6.21.pom" + ], + "hash": "sha256-tFZZFoP6YHGHAFr0sx0x1DYE4CHWBFUf8PIubdpWK5o=" + } + }, + "org.jetbrains.intellij.deps:trove4j:1.0.20200330": { + "trove4j-1.0.20200330.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.jar", + "https://repo.maven.apache.org/maven2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.jar" + ], + "hash": "sha256-xf1yW/+rUYRr88d9sTg8YKquv+G3/i8A0j/ht98KQ50=" + }, + "trove4j-1.0.20200330.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.pom", + "https://repo.maven.apache.org/maven2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.pom" + ], + "hash": "sha256-h3IcuqZaPJfYsbqdIHhA8WTJ/jh1n8nqEP/iZWX40+k=" + } + }, + "net.java.dev.jna:jna:5.6.0": { + "jna-5.6.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.jar", + "https://repo.maven.apache.org/maven2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.jar" + ], + "hash": "sha256-VVfiNaiqL5dm1dxgnWeUjyqIMsLXls6p7x1svgs7fq8=" + }, + "jna-5.6.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.pom", + "https://repo.maven.apache.org/maven2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.pom" + ], + "hash": "sha256-X+gbAlWXjyRhbTexBgi3lJil8wc+HZsgONhzaoMfJgg=" + } + }, + "org.jetbrains.kotlin:kotlin-annotation-processing-gradle:1.6.21": { + "kotlin-annotation-processing-gradle-1.6.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.6.21/kotlin-annotation-processing-gradle-1.6.21.jar" + ], + "hash": "sha256-tA86gSFVnlAjnFXvh2Z6IYBRG7GTQfzIYZh+T4TOYog=" + }, + "kotlin-annotation-processing-gradle-1.6.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.6.21/kotlin-annotation-processing-gradle-1.6.21.pom" + ], + "hash": "sha256-MImLOrD3X6VZjABz0qoqV9yctWnJ6Mb/O6UXUopMEHE=" + } + }, + "org.jetbrains.kotlin:kotlin-android-extensions:1.6.21": { + "kotlin-android-extensions-1.6.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-android-extensions/1.6.21/kotlin-android-extensions-1.6.21.jar" + ], + "hash": "sha256-QY25MO/hevs27AnooGI1615PYAsrXKFIeEIsn5lEbPs=" + }, + "kotlin-android-extensions-1.6.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-android-extensions/1.6.21/kotlin-android-extensions-1.6.21.pom" + ], + "hash": "sha256-oWU+E091vwu2aNklZdd/Qy3lGijcUcNK9eOBS53tCsQ=" + } + }, + "org.jetbrains.kotlin:kotlin-compiler-runner:1.6.21": { + "kotlin-compiler-runner-1.6.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-runner/1.6.21/kotlin-compiler-runner-1.6.21.jar" + ], + "hash": "sha256-IGGw47e3Uwv2cg2LBBC+Eyb7Fs1NrcN+d8Aqz+/loLM=" + }, + "kotlin-compiler-runner-1.6.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-runner/1.6.21/kotlin-compiler-runner-1.6.21.pom" + ], + "hash": "sha256-b0Ofb0jeG+QltfdQlLbqpICL6hG8LjzmtUTG4zOQtSU=" + } + }, + "org.jetbrains.kotlin:kotlin-build-common:1.6.21": { + "kotlin-build-common-1.6.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-build-common/1.6.21/kotlin-build-common-1.6.21.jar" + ], + "hash": "sha256-Y+6kBdNeNOggJcL0FW49R1fLjyWUmWIzVspma9IQAZ0=" + }, + "kotlin-build-common-1.6.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-build-common/1.6.21/kotlin-build-common-1.6.21.pom" + ], + "hash": "sha256-LRDfBINfB7h6qBoOf+xAbSwawRxU5+CPCOtRGv5btI8=" + } + }, + "org.jetbrains.kotlin:kotlin-daemon-client:1.6.21": { + "kotlin-daemon-client-1.6.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-client/1.6.21/kotlin-daemon-client-1.6.21.jar" + ], + "hash": "sha256-ZHawBzZPVFzmd6ObkzG8IbVqvXtWbwOfUfIVCKOQL6c=" + }, + "kotlin-daemon-client-1.6.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-client/1.6.21/kotlin-daemon-client-1.6.21.pom" + ], + "hash": "sha256-Q8EnIKTydrNdwEOWEo6bf7Goq9B6FstAnGwNZwaiMWs=" + } + }, + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.0": { + "kotlinx-coroutines-core-jvm-1.5.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.5.0/kotlinx-coroutines-core-jvm-1.5.0.jar" + ], + "hash": "sha256-eNbMcTX4TWkv83Uvz9H6G74JQNffcGUuTx6u7Ax4r7s=" + }, + "kotlinx-coroutines-core-jvm-1.5.0.module": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.5.0/kotlinx-coroutines-core-jvm-1.5.0.module" + ], + "hash": "sha256-yIXdAoEHbFhDgm3jF+PLzcPYhZ2+71OuHPrNG5xg+W4=" + } + }, + "org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.6.21": { + "kotlin-scripting-compiler-embeddable-1.6.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.6.21/kotlin-scripting-compiler-embeddable-1.6.21.jar", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.6.21/kotlin-scripting-compiler-embeddable-1.6.21.jar" + ], + "hash": "sha256-XJNzrzrkC3PW12JLJOjOEXIUSV2GLebSz7YYpxGRBrE=" + }, + "kotlin-scripting-compiler-embeddable-1.6.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.6.21/kotlin-scripting-compiler-embeddable-1.6.21.pom", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.6.21/kotlin-scripting-compiler-embeddable-1.6.21.pom" + ], + "hash": "sha256-C32qtju7PFTd0+NF6wzLI3aAv9TDh7Zfzllt/0uEe9s=" + } + }, + "org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.6.21": { + "kotlin-scripting-compiler-impl-embeddable-1.6.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.6.21/kotlin-scripting-compiler-impl-embeddable-1.6.21.jar", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.6.21/kotlin-scripting-compiler-impl-embeddable-1.6.21.jar" + ], + "hash": "sha256-5ARLjeAehGM5I3BvQ82oDTfYu++M6ahm+dlZYt3SBIA=" + }, + "kotlin-scripting-compiler-impl-embeddable-1.6.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.6.21/kotlin-scripting-compiler-impl-embeddable-1.6.21.pom", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.6.21/kotlin-scripting-compiler-impl-embeddable-1.6.21.pom" + ], + "hash": "sha256-gIxqOEi7Xk9sYWmKxYkxIVc8Q9s4FCNW6D3q0EyzhjQ=" + } + }, + "org.jetbrains.kotlin:kotlin-scripting-common:1.6.21": { + "kotlin-scripting-common-1.6.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-common/1.6.21/kotlin-scripting-common-1.6.21.jar", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.6.21/kotlin-scripting-common-1.6.21.jar" + ], + "hash": "sha256-v79fA2I3zTPCX7oz1IlI2ZXbgYbOPwnDGvnCnIDOnK4=" + }, + "kotlin-scripting-common-1.6.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-common/1.6.21/kotlin-scripting-common-1.6.21.pom", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.6.21/kotlin-scripting-common-1.6.21.pom" + ], + "hash": "sha256-qgWvDyJWUokIeXiduzo6UY4XdWqFsT1UCo3P3wPL+5w=" + } + }, + "org.jetbrains.kotlin:kotlin-scripting-jvm:1.6.21": { + "kotlin-scripting-jvm-1.6.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.6.21/kotlin-scripting-jvm-1.6.21.jar", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.6.21/kotlin-scripting-jvm-1.6.21.jar" + ], + "hash": "sha256-ksA/6r9L3ZLVoixRp0i9NAJ0Z8PY9MZftbV0uGsH0QQ=" + }, + "kotlin-scripting-jvm-1.6.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.6.21/kotlin-scripting-jvm-1.6.21.pom", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.6.21/kotlin-scripting-jvm-1.6.21.pom" + ], + "hash": "sha256-i5q1hXoYheSL2uAPqosix0sNPkCmNPyeCadG+op1fTI=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib:1.6.21": { + "kotlin-stdlib-1.6.21.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.6.21/kotlin-stdlib-1.6.21.jar" + ], + "hash": "sha256-c5xSZnK7M3Vzso9jr6gwbrCIsMOgln9W1sifSjASpJI=" + }, + "kotlin-stdlib-1.6.21.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.6.21/kotlin-stdlib-1.6.21.pom" + ], + "hash": "sha256-zkJyW6Ab2DbNqmZ9l032hL9vjxXng5JjMgraf/quHzQ=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib-common:1.6.21": { + "kotlin-stdlib-common-1.6.21.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.6.21/kotlin-stdlib-common-1.6.21.jar" + ], + "hash": "sha256-GDvsWc2fOhSVexkOjIec8RlL0fEGsKe24cu4eQ0kI2M=" + }, + "kotlin-stdlib-common-1.6.21.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.6.21/kotlin-stdlib-common-1.6.21.pom" + ], + "hash": "sha256-W8FW7nP9PC2sil7FSNWBtjMzNUfC/r7Zz2VH//FSa6I=" + } + }, + "org.jetbrains:annotations:13.0": { + "annotations-13.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/annotations/13.0/annotations-13.0.jar" + ], + "hash": "sha256-rOKhDcji1f00kl7KwD5JiLLA+FFlDJS4zvSbob0RFHg=" + }, + "annotations-13.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/annotations/13.0/annotations-13.0.pom" + ], + "hash": "sha256-llrrK+3/NpgZvd4b96CzuJuCR91pyIuGN112Fju4w5c=" + } + }, + "com.natpryce:konfig:1.6.10.0": { + "konfig-1.6.10.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/natpryce/konfig/1.6.10.0/konfig-1.6.10.0.jar" + ], + "hash": "sha256-1Va6vANYRVP1/TzEaJTF6jMxCSv7qufqYm1bjUznk7s=" + }, + "konfig-1.6.10.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/natpryce/konfig/1.6.10.0/konfig-1.6.10.0.pom" + ], + "hash": "sha256-1NTlAHxEbyBlnbIqc2WXwLCFOLy6FL1HEND4VNxxFYg=" + } + }, + "com.github.pengrad:java-telegram-bot-api:4.6.0": { + "java-telegram-bot-api-4.6.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/github/pengrad/java-telegram-bot-api/4.6.0/java-telegram-bot-api-4.6.0.jar" + ], + "hash": "sha256-w4H/cErewM/mZbrnUYtwiT5Czf83Smb0qYxGfeG/TdU=" + }, + "java-telegram-bot-api-4.6.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/github/pengrad/java-telegram-bot-api/4.6.0/java-telegram-bot-api-4.6.0.pom" + ], + "hash": "sha256-nZxF//5qwbIbZffUK0k2T/gnnX5pLU9wF0BLLhC+YsE=" + } + }, + "com.google.code.gson:gson:2.8.5": { + "gson-2.8.5.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/google/code/gson/gson/2.8.5/gson-2.8.5.jar" + ], + "hash": "sha256-IzoBSfw2XJ9u29aDz+JmsZvcdzvpjqva9rPJJLSOfYE=" + }, + "gson-2.8.5.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/google/code/gson/gson/2.8.5/gson-2.8.5.pom" + ], + "hash": "sha256-uDCFV6f8zJLZ/nyM0FmSWLNhKF0uzedontqYhDJVoJI=" + } + }, + "com.squareup.okhttp3:okhttp:3.12.3": { + "okhttp-3.12.3.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/okhttp3/okhttp/3.12.3/okhttp-3.12.3.jar" + ], + "hash": "sha256-gUWW1U7f2Ut9nYcSvzeYZ9ObCQQo3TjFEG0N7V2jVv8=" + }, + "okhttp-3.12.3.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/okhttp3/okhttp/3.12.3/okhttp-3.12.3.pom" + ], + "hash": "sha256-xXZHCTgwkLDEfEiizwh2OTvt1Ihmv83hk0NJf/oXuEQ=" + } + }, + "com.squareup.okio:okio:1.15.0": { + "okio-1.15.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/1.15.0/okio-1.15.0.jar" + ], + "hash": "sha256-aT+jGafohDMAYCsgQCO3Z08Qbry1d/LdWAchK2YRi9I=" + }, + "okio-1.15.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/1.15.0/okio-1.15.0.pom" + ], + "hash": "sha256-8cELFIDRq3X7BRoHsnPjfNolJel+Fgfug+aDO3Dhv84=" + } + }, + "com.squareup.okhttp3:logging-interceptor:3.12.3": { + "logging-interceptor-3.12.3.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/okhttp3/logging-interceptor/3.12.3/logging-interceptor-3.12.3.jar" + ], + "hash": "sha256-NNEihOBDYkI+VFe03a74xNhLyNgN1K0ZQ+Y8hQf4FXY=" + }, + "logging-interceptor-3.12.3.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/okhttp3/logging-interceptor/3.12.3/logging-interceptor-3.12.3.pom" + ], + "hash": "sha256-H/YmwXE+Itb1bpLtvctOnBRMszSoT6gAsHAfmW+xp/I=" + } + }, + "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3": { + "kotlinx-coroutines-core-1.3.3.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core/1.3.3/kotlinx-coroutines-core-1.3.3.jar" + ], + "hash": "sha256-91+LDzJgcX1FNZ+elv9mYT+gY+QGUSCwZ8yQcleghmo=" + }, + "kotlinx-coroutines-core-1.3.3.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core/1.3.3/kotlinx-coroutines-core-1.3.3.pom" + ], + "hash": "sha256-KZmeUobJiKm3K3xt/rmE2fohxRcY9bb5P1Yh5wClN/4=" + } + }, + "io.javalin:javalin:3.7.0": { + "javalin-3.7.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/io/javalin/javalin/3.7.0/javalin-3.7.0.jar" + ], + "hash": "sha256-YGYQPPI2In7IacUllknrErvlwFyH8MHp9y86RGYOZ3I=" + }, + "javalin-3.7.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/io/javalin/javalin/3.7.0/javalin-3.7.0.pom" + ], + "hash": "sha256-11U3Www5qZiAEH3sDAzdMgDx7qi2npxtFkYdyuR050M=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.61": { + "kotlin-stdlib-jdk8-1.3.61.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.3.61/kotlin-stdlib-jdk8-1.3.61.jar" + ], + "hash": "sha256-ODm6fet5g3XaGAe8Rp0c8xXbemJ1WZ9zMYQ3R3LsOyE=" + }, + "kotlin-stdlib-jdk8-1.3.61.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.3.61/kotlin-stdlib-jdk8-1.3.61.pom" + ], + "hash": "sha256-4wGH5XIMpkC45oaG8g3QJQ3O8Bk9VuVWnDxKYSdzErY=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.61": { + "kotlin-stdlib-jdk7-1.3.61.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.3.61/kotlin-stdlib-jdk7-1.3.61.jar" + ], + "hash": "sha256-EfSlfj59gfPxUtXc7+Ob13YUtalBJf87EVJrChmsOYk=" + }, + "kotlin-stdlib-jdk7-1.3.61.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.3.61/kotlin-stdlib-jdk7-1.3.61.pom" + ], + "hash": "sha256-xBYICuq9uRGKCO54wo4oVgOM2FhYQipx98Rr8nb2Z6c=" + } + }, + "org.slf4j:slf4j-api:1.8.0-beta4": { + "slf4j-api-1.8.0-beta4.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/slf4j/slf4j-api/1.8.0-beta4/slf4j-api-1.8.0-beta4.jar" + ], + "hash": "sha256-YCtxIynIS0qDxARk9P39D+QjjFPvOXE5qGcGRznb9OA=" + }, + "slf4j-api-1.8.0-beta4.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/slf4j/slf4j-api/1.8.0-beta4/slf4j-api-1.8.0-beta4.pom" + ], + "hash": "sha256-+DFtKKzyUrIbHp6O7ZqEwq+9yOBA9p06ELq4E9PYWoU=" + } + }, + "org.eclipse.jetty:jetty-server:9.4.25.v20191220": { + "jetty-server-9.4.25.v20191220.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/jetty-server/9.4.25.v20191220/jetty-server-9.4.25.v20191220.jar" + ], + "hash": "sha256-z89tvOS+zuXwZw2bx6do0bc87wyEZj6CrMC5EN8lZfQ=" + }, + "jetty-server-9.4.25.v20191220.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/jetty-server/9.4.25.v20191220/jetty-server-9.4.25.v20191220.pom" + ], + "hash": "sha256-uWOogVUMUf5hOTgJbqfwWZLoGzBBy8faXgb6+8/YZWk=" + } + }, + "javax.servlet:javax.servlet-api:3.1.0": { + "javax.servlet-api-3.1.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0.jar" + ], + "hash": "sha256-r0VrLdQcToLPVPPnQ7xniXPZ/jW9TTBx+gXH5TM7hII=" + }, + "javax.servlet-api-3.1.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0.pom" + ], + "hash": "sha256-sxEJ4i6j8t8a15VUMucYo13vUK5sGWmANK+ooM+ekGk=" + } + }, + "org.eclipse.jetty:jetty-http:9.4.25.v20191220": { + "jetty-http-9.4.25.v20191220.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/jetty-http/9.4.25.v20191220/jetty-http-9.4.25.v20191220.jar" + ], + "hash": "sha256-3JxGbw/kvzf9X02iPQFoSwZ63poWAsTzxbaUvMIIR7o=" + }, + "jetty-http-9.4.25.v20191220.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/jetty-http/9.4.25.v20191220/jetty-http-9.4.25.v20191220.pom" + ], + "hash": "sha256-upIlnnZtESJEah+zuPZAXnroxcQS8i6XbLCEyoxhm4c=" + } + }, + "org.eclipse.jetty:jetty-util:9.4.25.v20191220": { + "jetty-util-9.4.25.v20191220.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/jetty-util/9.4.25.v20191220/jetty-util-9.4.25.v20191220.jar" + ], + "hash": "sha256-IjeA1yTBx0Y8MjOoLAdobz/XigIvVg0BAlfb5AKODRQ=" + }, + "jetty-util-9.4.25.v20191220.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/jetty-util/9.4.25.v20191220/jetty-util-9.4.25.v20191220.pom" + ], + "hash": "sha256-iEWSOTxmB1pqb6Z9iY532crIf1lIy10xDPyN5Z7wE8Y=" + } + }, + "org.eclipse.jetty:jetty-io:9.4.25.v20191220": { + "jetty-io-9.4.25.v20191220.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/jetty-io/9.4.25.v20191220/jetty-io-9.4.25.v20191220.jar" + ], + "hash": "sha256-6cMdtQO2B1/UPxVTGQMAfB6Cn8JF2jQEtuQyfyTvlWk=" + }, + "jetty-io-9.4.25.v20191220.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/jetty-io/9.4.25.v20191220/jetty-io-9.4.25.v20191220.pom" + ], + "hash": "sha256-q1nyQDwSIWhSvBzyhOVhETo9LgsZUmMwmLBfOQW9kYE=" + } + }, + "org.eclipse.jetty:jetty-webapp:9.4.25.v20191220": { + "jetty-webapp-9.4.25.v20191220.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/jetty-webapp/9.4.25.v20191220/jetty-webapp-9.4.25.v20191220.jar" + ], + "hash": "sha256-qnWB2sNcrVdLA82aFEuibc9DeZ0k7P9enzoGiKJzLvE=" + }, + "jetty-webapp-9.4.25.v20191220.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/jetty-webapp/9.4.25.v20191220/jetty-webapp-9.4.25.v20191220.pom" + ], + "hash": "sha256-HRXbctxeN+O+7iEjd1PsYkXn/sXj/ehUK5Yf/ZB9Ufw=" + } + }, + "org.eclipse.jetty:jetty-xml:9.4.25.v20191220": { + "jetty-xml-9.4.25.v20191220.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/jetty-xml/9.4.25.v20191220/jetty-xml-9.4.25.v20191220.jar" + ], + "hash": "sha256-+xNsUWNTj8WHQuqlbfRIdlu4FvJd43Hasf6u5612tN8=" + }, + "jetty-xml-9.4.25.v20191220.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/jetty-xml/9.4.25.v20191220/jetty-xml-9.4.25.v20191220.pom" + ], + "hash": "sha256-05fGZk1fr9j7VX7NJU4EZP16bakwG60B4C248SAFvrM=" + } + }, + "org.eclipse.jetty:jetty-servlet:9.4.25.v20191220": { + "jetty-servlet-9.4.25.v20191220.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/jetty-servlet/9.4.25.v20191220/jetty-servlet-9.4.25.v20191220.jar" + ], + "hash": "sha256-LU0t1OZdCWL0/xHTycytMKYmN3fgVpwbVzE4aLNHchw=" + }, + "jetty-servlet-9.4.25.v20191220.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/jetty-servlet/9.4.25.v20191220/jetty-servlet-9.4.25.v20191220.pom" + ], + "hash": "sha256-tw95bbbqAGKLv7ph5aLgMRLjJ10OaIHJN/ARwn/wXos=" + } + }, + "org.eclipse.jetty:jetty-security:9.4.25.v20191220": { + "jetty-security-9.4.25.v20191220.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/jetty-security/9.4.25.v20191220/jetty-security-9.4.25.v20191220.jar" + ], + "hash": "sha256-Y3HBY7kqyNb6sIyx2rkdDmkOclZoc9j3g706d5Oj2iY=" + }, + "jetty-security-9.4.25.v20191220.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/jetty-security/9.4.25.v20191220/jetty-security-9.4.25.v20191220.pom" + ], + "hash": "sha256-2j1qeYtoSPOXIPxweDTha+S8pC31qiXCWSK5Mvz+rus=" + } + }, + "org.eclipse.jetty.websocket:websocket-server:9.4.25.v20191220": { + "websocket-server-9.4.25.v20191220.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/websocket/websocket-server/9.4.25.v20191220/websocket-server-9.4.25.v20191220.jar" + ], + "hash": "sha256-PjO/DwuuXX+/Rx16JWroB4UCkGoxIaCgANkU39F21bo=" + }, + "websocket-server-9.4.25.v20191220.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/websocket/websocket-server/9.4.25.v20191220/websocket-server-9.4.25.v20191220.pom" + ], + "hash": "sha256-o9WaXSoxrXskMRuXh2Eog5sNeO+oH4blG6yqelb5MKQ=" + } + }, + "org.eclipse.jetty.websocket:websocket-common:9.4.25.v20191220": { + "websocket-common-9.4.25.v20191220.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/websocket/websocket-common/9.4.25.v20191220/websocket-common-9.4.25.v20191220.jar" + ], + "hash": "sha256-1bvWkUvEIbKOB6MXkc2ZKgBnQX1rX9Bapkq1hDrydzw=" + }, + "websocket-common-9.4.25.v20191220.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/websocket/websocket-common/9.4.25.v20191220/websocket-common-9.4.25.v20191220.pom" + ], + "hash": "sha256-ukxD7w1zKeye8StLaAa+D3rHPCQRm8vkvj1m7ebbmlQ=" + } + }, + "org.eclipse.jetty.websocket:websocket-api:9.4.25.v20191220": { + "websocket-api-9.4.25.v20191220.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/websocket/websocket-api/9.4.25.v20191220/websocket-api-9.4.25.v20191220.jar" + ], + "hash": "sha256-sRCCel9HyDUQMj7hm+h+N7FUDhVTfNAhqTVJ4El0f68=" + }, + "websocket-api-9.4.25.v20191220.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/websocket/websocket-api/9.4.25.v20191220/websocket-api-9.4.25.v20191220.pom" + ], + "hash": "sha256-xn/BVBQDGiWCGJri17IMVhDTUvWkf4fSi8+1lJQTWcs=" + } + }, + "org.eclipse.jetty.websocket:websocket-client:9.4.25.v20191220": { + "websocket-client-9.4.25.v20191220.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/websocket/websocket-client/9.4.25.v20191220/websocket-client-9.4.25.v20191220.jar" + ], + "hash": "sha256-dIMBH4pyWNlP62P+SjZSCYG8HYXsPdGxSJlX1AcRFOw=" + }, + "websocket-client-9.4.25.v20191220.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/websocket/websocket-client/9.4.25.v20191220/websocket-client-9.4.25.v20191220.pom" + ], + "hash": "sha256-AzAQdDEZ7xKiB2CXLdHAu6BwLuiVU5LtP/QdF2RMOs4=" + } + }, + "org.eclipse.jetty:jetty-client:9.4.25.v20191220": { + "jetty-client-9.4.25.v20191220.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/jetty-client/9.4.25.v20191220/jetty-client-9.4.25.v20191220.jar" + ], + "hash": "sha256-qwUsaY1GjdLLjZ1bcH5VqUQDDZFfT59BrDzc+Cs9xuA=" + }, + "jetty-client-9.4.25.v20191220.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/jetty-client/9.4.25.v20191220/jetty-client-9.4.25.v20191220.pom" + ], + "hash": "sha256-ixNwOlizo3BtJIiemlXDSRu+XY+DZdOoKkvvqcbp+eM=" + } + }, + "org.eclipse.jetty.websocket:websocket-servlet:9.4.25.v20191220": { + "websocket-servlet-9.4.25.v20191220.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/websocket/websocket-servlet/9.4.25.v20191220/websocket-servlet-9.4.25.v20191220.jar" + ], + "hash": "sha256-nYoe6bmGzp/JJM3ai9fvzxwLZ0X3qWa1B8x3WU/vIms=" + }, + "websocket-servlet-9.4.25.v20191220.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/eclipse/jetty/websocket/websocket-servlet/9.4.25.v20191220/websocket-servlet-9.4.25.v20191220.pom" + ], + "hash": "sha256-WgVNHE2/17gfAqoOIR+pm7ZHZEn6T48swQGjvPtT7wY=" + } + }, + "org.slf4j:slf4j-simple:1.8.0-beta4": { + "slf4j-simple-1.8.0-beta4.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/slf4j/slf4j-simple/1.8.0-beta4/slf4j-simple-1.8.0-beta4.jar" + ], + "hash": "sha256-usZqvFtEYt/2Lh4ZqzsKZcFg681WTPJZENsAOo5WnP0=" + }, + "slf4j-simple-1.8.0-beta4.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/slf4j/slf4j-simple/1.8.0-beta4/slf4j-simple-1.8.0-beta4.pom" + ], + "hash": "sha256-oXrS6OU00OgZ6o0UIT3nSNRlD/8qJX0+kqE9oxAoe/c=" + } + }, + "org.xerial:sqlite-jdbc:3.30.1": { + "sqlite-jdbc-3.30.1.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/xerial/sqlite-jdbc/3.30.1/sqlite-jdbc-3.30.1.jar" + ], + "hash": "sha256-KAA0qJkwABBMWza8XhE5sOgt8d6c/ZUfUpva3q9vRW0=" + }, + "sqlite-jdbc-3.30.1.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/xerial/sqlite-jdbc/3.30.1/sqlite-jdbc-3.30.1.pom" + ], + "hash": "sha256-eGpZKh7AtwPJJVOlE37gAxGb5UmlGTM05t44WrKGb3I=" + } + }, + "org.postgresql:postgresql:42.2.2": { + "postgresql-42.2.2.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/postgresql/postgresql/42.2.2/postgresql-42.2.2.jar" + ], + "hash": "sha256-GZZSQCajAnhT85MuhjnvgTgH0bY/4Ugy9BD/+kJ0+nA=" + }, + "postgresql-42.2.2.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/postgresql/postgresql/42.2.2/postgresql-42.2.2.pom" + ], + "hash": "sha256-NbNCwrBu1Cf6VP/xw3GNQ2HvrcNC7DJM7DnBeKm481Y=" + } + }, + "com.fasterxml.jackson.core:jackson-databind:2.10.1": { + "jackson-databind-2.10.1.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.10.1/jackson-databind-2.10.1.jar" + ], + "hash": "sha256-LSP0cAFJIjNWWt9aNPIl8q6JVkzuCAJIc+w2t4Qu3kY=" + }, + "jackson-databind-2.10.1.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.10.1/jackson-databind-2.10.1.pom" + ], + "hash": "sha256-OGlQZeP1ILBbvY6lmC5ba1vZ+FYpZ7g9rLfQerCMauc=" + } + }, + "com.fasterxml.jackson.core:jackson-annotations:2.10.1": { + "jackson-annotations-2.10.1.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.10.1/jackson-annotations-2.10.1.jar" + ], + "hash": "sha256-Zz+K4Wvs6k+pN0BLOoUUF/r0LfO7xZICi74r/gzJ2Ms=" + }, + "jackson-annotations-2.10.1.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.10.1/jackson-annotations-2.10.1.pom" + ], + "hash": "sha256-7OURA2Z+iBHw/3RYmGryFxhi5UuYE8FwjPk3kESH+Vw=" + } + }, + "com.fasterxml.jackson.core:jackson-core:2.10.1": { + "jackson-core-2.10.1.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-core/2.10.1/jackson-core-2.10.1.jar" + ], + "hash": "sha256-eb/73NNJ9ppawlLitAlhMXBDhq9PoU2VOV6poOQjzzM=" + }, + "jackson-core-2.10.1.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-core/2.10.1/jackson-core-2.10.1.pom" + ], + "hash": "sha256-EXkJC3ILJankJmQwLwM0oiQLMMcoC0IkJeT0UZ5bLP4=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib:1.3.61": { + "kotlin-stdlib-1.3.61.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.3.61/kotlin-stdlib-1.3.61.jar" + ], + "hash": "sha256-5R5RJhmn52UKMOtOs+nAPmkJx7XjwCZATgdiVMCYuTI=" + }, + "kotlin-stdlib-1.3.61.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.3.61/kotlin-stdlib-1.3.61.pom" + ], + "hash": "sha256-2+W6vNjUPpsIwoRWgLU/wbs+BRxIBYAt3Q7T6OLFCoQ=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib-common:1.3.61": { + "kotlin-stdlib-common-1.3.61.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.3.61/kotlin-stdlib-common-1.3.61.jar" + ], + "hash": "sha256-oufzQc8wR7XwChkX73d9MjzasqVzd0aLjtYqoxRpz38=" + }, + "kotlin-stdlib-common-1.3.61.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.3.61/kotlin-stdlib-common-1.3.61.pom" + ], + "hash": "sha256-4i2wCbsaYWNtlCVjWYlzbbXj/KSUgJq/JERo3EdM/AQ=" + } + }, + "org.jetbrains.kotlin:kotlin-script-runtime:1.6.21": { + "kotlin-script-runtime-1.6.21.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-script-runtime/1.6.21/kotlin-script-runtime-1.6.21.jar" + ], + "hash": "sha256-YGw0p+bo5DnpIIdl59dbHbz4Dzg1Pz4puydFbXs3EXE=" + }, + "kotlin-script-runtime-1.6.21.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-script-runtime/1.6.21/kotlin-script-runtime-1.6.21.pom" + ], + "hash": "sha256-jVeQOOsdLK0DMFKOKdyMy4rozQ1WClRMXBswqT7O/t4=" + } + }, + "org.jetbrains.kotlin:kotlin-reflect:1.6.21": { + "kotlin-reflect-1.6.21.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.6.21/kotlin-reflect-1.6.21.jar" + ], + "hash": "sha256-Hh9XIJ9yOMP9FzWhuTOaVlZVB9yiSfg3G/WdkfYBrqo=" + }, + "kotlin-reflect-1.6.21.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.6.21/kotlin-reflect-1.6.21.pom" + ], + "hash": "sha256-2nHh493COI1nVkFnLi8DFtucnSEvlG8CbUoOahM2p/M=" + } + }, + "org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:1.6.21": { + "kotlin-klib-commonizer-embeddable-1.6.21.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-klib-commonizer-embeddable/1.6.21/kotlin-klib-commonizer-embeddable-1.6.21.jar" + ], + "hash": "sha256-1jgafq67fkj8p2v1u55fQ/pW3eb9UQXK6N4TXmMoD3A=" + }, + "kotlin-klib-commonizer-embeddable-1.6.21.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-klib-commonizer-embeddable/1.6.21/kotlin-klib-commonizer-embeddable-1.6.21.pom" + ], + "hash": "sha256-bz7nSBQNsbaG5nqJehadbeQv1nQkHVVA3FK7o2Re/i4=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21": { + "kotlin-stdlib-jdk8-1.6.21.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.6.21/kotlin-stdlib-jdk8-1.6.21.jar" + ], + "hash": "sha256-2rRUibR3NtWfzkS4BnbxlHqba8qxD9YOh4qDvYKmlUw=" + }, + "kotlin-stdlib-jdk8-1.6.21.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.6.21/kotlin-stdlib-jdk8-1.6.21.pom" + ], + "hash": "sha256-g2oReaCNJJFGl9JhLgO4SKCHyAy0sMoj+c+rJH86dcQ=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.21": { + "kotlin-stdlib-jdk7-1.6.21.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.6.21/kotlin-stdlib-jdk7-1.6.21.jar" + ], + "hash": "sha256-8bBjTbuUFyA4RjAguy3UXKJoSfjOKdYlrLDxVp0R2+4=" + }, + "kotlin-stdlib-jdk7-1.6.21.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.6.21/kotlin-stdlib-jdk7-1.6.21.pom" + ], + "hash": "sha256-ARzSjruf3oFrA1nVrhCjZ07A/yxTEMBBLCDv6Oo9oG4=" + } + }, + "com.winterbe:expekt:0.5.0": { + "expekt-0.5.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/winterbe/expekt/0.5.0/expekt-0.5.0.jar" + ], + "hash": "sha256-mKJnQqgnRs1u5m7/u8PK/TInA+onhhf734u5tU3O8Xw=" + }, + "expekt-0.5.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/winterbe/expekt/0.5.0/expekt-0.5.0.pom" + ], + "hash": "sha256-We03cwfzVZIPORBAQ6YBDDrnbKWfKULGxk3Ttg0pEsc=" + } + }, + "org.spekframework.spek2:spek-dsl-jvm:2.0.9": { + "spek-dsl-jvm-2.0.9.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/spekframework/spek2/spek-dsl-jvm/2.0.9/spek-dsl-jvm-2.0.9.jar" + ], + "hash": "sha256-gohf+MCcJfvntBQS/IoIyCAn8kuE6gH3ZL5jm8CYGeg=" + }, + "spek-dsl-jvm-2.0.9.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/spekframework/spek2/spek-dsl-jvm/2.0.9/spek-dsl-jvm-2.0.9.pom" + ], + "hash": "sha256-q3b2C4rYViJC615qA1SLpiL6xHDFpE6pzckZ34VzgQQ=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib:1.0.3": { + "kotlin-stdlib-1.0.3.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.0.3/kotlin-stdlib-1.0.3.jar" + ], + "hash": "sha256-ZyHVKFgAZF7WgZP35t0H0srOCd6fO3XN8fMFD0Y1l4E=" + }, + "kotlin-stdlib-1.0.3.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.0.3/kotlin-stdlib-1.0.3.pom" + ], + "hash": "sha256-QK5yi+5hvXgSHcWjdko/vH1jRYaHuRmI2qXKMhFQNx0=" + } + }, + "org.jetbrains.kotlin:kotlin-runtime:1.0.3": { + "kotlin-runtime-1.0.3.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-runtime/1.0.3/kotlin-runtime-1.0.3.jar" + ], + "hash": "sha256-jBkPOBLPoR0I6wFBuMh36jJC8N3Q6r/llSV0Pq5ifo4=" + }, + "kotlin-runtime-1.0.3.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-runtime/1.0.3/kotlin-runtime-1.0.3.pom" + ], + "hash": "sha256-LaX+tSEGymCnZiDUaRgktUkbyi7ojMJVcwALCX3lRRc=" + } + }, + "org.spekframework.spek2:spek-runner-junit5:2.0.9": { + "spek-runner-junit5-2.0.9.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/spekframework/spek2/spek-runner-junit5/2.0.9/spek-runner-junit5-2.0.9.jar" + ], + "hash": "sha256-K0ZmWbdh12OKtc2CX8yC3CrA1FPJ6yAKGUAHG4KkpYY=" + }, + "spek-runner-junit5-2.0.9.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/spekframework/spek2/spek-runner-junit5/2.0.9/spek-runner-junit5-2.0.9.pom" + ], + "hash": "sha256-7GcxgitATmAvUWoOpzJFBWgHoMWg2Kb4SkTjqnfrSjg=" + } + }, + "org.spekframework.spek2:spek-runtime-jvm:2.0.9": { + "spek-runtime-jvm-2.0.9.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/spekframework/spek2/spek-runtime-jvm/2.0.9/spek-runtime-jvm-2.0.9.jar" + ], + "hash": "sha256-dZ18fuF78XJYwySioaGwhusrz2QnnBfh+av1Xsph+nQ=" + }, + "spek-runtime-jvm-2.0.9.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/spekframework/spek2/spek-runtime-jvm/2.0.9/spek-runtime-jvm-2.0.9.pom" + ], + "hash": "sha256-9o3lUgIMgh6TRueEI5uGtT5rR1+2DQRoWsdGILeiKeU=" + } + }, + "org.jetbrains.kotlin:kotlin-reflect:1.3.50": { + "kotlin-reflect-1.3.50.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.3.50/kotlin-reflect-1.3.50.jar" + ], + "hash": "sha256-ZFgxmepaVK79G9FZUoiSX3hCJu5WLR3SeQEcYHWz16Q=" + }, + "kotlin-reflect-1.3.50.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.3.50/kotlin-reflect-1.3.50.pom" + ], + "hash": "sha256-h0UYHlo+C6/v1GMJxrgQ33JT83n+uYUTHq+NTZwwJjU=" + } + }, + "io.github.classgraph:classgraph:4.8.37": { + "classgraph-4.8.37.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/io/github/classgraph/classgraph/4.8.37/classgraph-4.8.37.jar" + ], + "hash": "sha256-fR0+iCjB7vVJ1B7x7Oc9LFxYz7lRs/Igzwzx3SVVgXM=" + }, + "classgraph-4.8.37.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/io/github/classgraph/classgraph/4.8.37/classgraph-4.8.37.pom" + ], + "hash": "sha256-pJBV0GEleGZQvjPu13rphQCROLhNOWA7wesu08gIWzQ=" + } + }, + "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.0": { + "kotlinx-coroutines-core-common-1.3.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core-common/1.3.0/kotlinx-coroutines-core-common-1.3.0.jar" + ], + "hash": "sha256-Evof8J9dtFxlGJKP9HmjZPOqEXSRW6JgWkIF7GCwGMM=" + }, + "kotlinx-coroutines-core-common-1.3.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core-common/1.3.0/kotlinx-coroutines-core-common-1.3.0.pom" + ], + "hash": "sha256-V2kqeg3vYTmMQz4s87C0p0l4ZpQuBLFFshG1t57CoYM=" + } + }, + "org.junit.platform:junit-platform-engine:1.5.2": { + "junit-platform-engine-1.5.2.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/junit/platform/junit-platform-engine/1.5.2/junit-platform-engine-1.5.2.jar" + ], + "hash": "sha256-/yC6StjADvF7rvnFVRL5wC2aaHQPfxrAGppqoCOZMfg=" + }, + "junit-platform-engine-1.5.2.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/junit/platform/junit-platform-engine/1.5.2/junit-platform-engine-1.5.2.pom" + ], + "hash": "sha256-LUuVVVwh4IXrwd299C156x1VZA3Bk7G35hACQP0vGJ8=" + } + }, + "org.apiguardian:apiguardian-api:1.1.0": { + "apiguardian-api-1.1.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/apiguardian/apiguardian-api/1.1.0/apiguardian-api-1.1.0.jar" + ], + "hash": "sha256-qarp/4rj4XoqGPeRdegrFiZ8JG+708qd+7spCwjc/dQ=" + }, + "apiguardian-api-1.1.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/apiguardian/apiguardian-api/1.1.0/apiguardian-api-1.1.0.pom" + ], + "hash": "sha256-qUW5y1zZt3sscRhE5lnEPsBw71nZ9Qn6n0wYYbSGJxE=" + } + }, + "org.opentest4j:opentest4j:1.2.0": { + "opentest4j-1.2.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/opentest4j/opentest4j/1.2.0/opentest4j-1.2.0.jar" + ], + "hash": "sha256-WIEt5giY2Xb7ge87YtoFxmBMGP1KJJ9QRCgkefwoavI=" + }, + "opentest4j-1.2.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/opentest4j/opentest4j/1.2.0/opentest4j-1.2.0.pom" + ], + "hash": "sha256-qW5nGBbB/4gDvex0ySQfAlvfsnfaXStO4CJmQFk2+ZQ=" + } + }, + "org.junit.platform:junit-platform-commons:1.5.2": { + "junit-platform-commons-1.5.2.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/junit/platform/junit-platform-commons/1.5.2/junit-platform-commons-1.5.2.jar" + ], + "hash": "sha256-/ESv38DyDIXnGmbnlDKBrvO8Hg/WLS1po2y2kB5oLBA=" + }, + "junit-platform-commons-1.5.2.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/junit/platform/junit-platform-commons/1.5.2/junit-platform-commons-1.5.2.pom" + ], + "hash": "sha256-O9DU3tYyqK+MpYf7Z2QBnedxsda8uJrNViQ1oQCfqto=" + } + } +} \ No newline at end of file diff --git a/fixtures/golden/buildsrc/plugin-in-buildsrc.kotlin.json b/fixtures/golden/buildsrc/plugin-in-buildsrc.kotlin.json new file mode 100644 index 0000000..5be4cf3 --- /dev/null +++ b/fixtures/golden/buildsrc/plugin-in-buildsrc.kotlin.json @@ -0,0 +1,576 @@ +{ + "org.gradle.kotlin.kotlin-dsl:org.gradle.kotlin.kotlin-dsl.gradle.plugin:4.1.0": { + "org.gradle.kotlin.kotlin-dsl.gradle.plugin-4.1.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/gradle/kotlin/kotlin-dsl/org.gradle.kotlin.kotlin-dsl.gradle.plugin/4.1.0/org.gradle.kotlin.kotlin-dsl.gradle.plugin-4.1.0.pom" + ], + "hash": "sha256-PKFoMBmO4Pc//RRgknW3A5zR/seULCInsEX6JpbjV2c=" + } + }, + "org.gradle.kotlin:gradle-kotlin-dsl-plugins:4.1.0": { + "gradle-kotlin-dsl-plugins-4.1.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/gradle/kotlin/gradle-kotlin-dsl-plugins/4.1.0/gradle-kotlin-dsl-plugins-4.1.0.jar" + ], + "hash": "sha256-jpBY+e9xNsVaJKXPKgoZKNb9oYJ2JZ0KktaxAr8m1Cc=" + }, + "gradle-kotlin-dsl-plugins-4.1.0.module": { + "urls": [ + "https://plugins.gradle.org/m2/org/gradle/kotlin/gradle-kotlin-dsl-plugins/4.1.0/gradle-kotlin-dsl-plugins-4.1.0.module" + ], + "hash": "sha256-0KuS4r6L+a8iIhAL4VOLP2R7SvA0+ZA1RJGKO4dxrq8=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0": { + "kotlin-stdlib-jdk8-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.9.0/kotlin-stdlib-jdk8-1.9.0.jar" + ], + "hash": "sha256-pZ+iT98f+1lLrs2/D9EAEPl3zqECNtSH/jRkl3pzd/o=" + }, + "kotlin-stdlib-jdk8-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.9.0/kotlin-stdlib-jdk8-1.9.0.pom" + ], + "hash": "sha256-ZNWY3YjiUEZnMeIDBKtvBsu7urfuMitHA7a1n4gcT5I=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib:1.9.0": { + "kotlin-stdlib-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-stdlib/1.9.0/kotlin-stdlib-1.9.0.jar" + ], + "hash": "sha256-Na7/vi21qkRgcs7lD87ki3+p4vxRyjfAzH19C8OdlS4=" + }, + "kotlin-stdlib-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-stdlib/1.9.0/kotlin-stdlib-1.9.0.pom" + ], + "hash": "sha256-N3UiY/Ysw+MlCFbiiO5Kc9QQLXJqd2JwNPlIBsjBCso=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib-common:1.9.0": { + "kotlin-stdlib-common-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-stdlib-common/1.9.0/kotlin-stdlib-common-1.9.0.jar" + ], + "hash": "sha256-KDJ0IEvXwCB4nsRvj45yr0JE1/VQszkqV+XKAGrXqiw=" + }, + "kotlin-stdlib-common-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-stdlib-common/1.9.0/kotlin-stdlib-common-1.9.0.pom" + ], + "hash": "sha256-NmDTanD+s6vknxG5BjPkHTYnNXbwcbDhCdqbOg3wgqU=" + } + }, + "org.jetbrains:annotations:13.0": { + "annotations-13.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/annotations/13.0/annotations-13.0.jar" + ], + "hash": "sha256-rOKhDcji1f00kl7KwD5JiLLA+FFlDJS4zvSbob0RFHg=" + }, + "annotations-13.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/annotations/13.0/annotations-13.0.pom" + ], + "hash": "sha256-llrrK+3/NpgZvd4b96CzuJuCR91pyIuGN112Fju4w5c=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0": { + "kotlin-stdlib-jdk7-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.9.0/kotlin-stdlib-jdk7-1.9.0.jar" + ], + "hash": "sha256-t5eaeqyUBV8Nnx/TtHzl/+HLYDKoQrqfvnGG8IUokXg=" + }, + "kotlin-stdlib-jdk7-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.9.0/kotlin-stdlib-jdk7-1.9.0.pom" + ], + "hash": "sha256-wRB08MiYqYuGPGFEcdQ409+Soewzgqbjf5NdfXGVS1o=" + } + }, + "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0": { + "kotlin-gradle-plugin-1.9.0-gradle81.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin/1.9.0/kotlin-gradle-plugin-1.9.0-gradle81.jar" + ], + "hash": "sha256-2UOg4ntHRuAfg0BaSfUmoi9HGx2x1GOdb84m1xHv+/4=" + }, + "kotlin-gradle-plugin-1.9.0.module": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin/1.9.0/kotlin-gradle-plugin-1.9.0.module" + ], + "hash": "sha256-/mOWRe2PvcW8Et588lRopNsx52O6ea26ogahTeYP0xQ=" + } + }, + "org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.9.0": { + "kotlin-gradle-plugin-api-1.9.0-gradle81.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.9.0/kotlin-gradle-plugin-api-1.9.0-gradle81.jar" + ], + "hash": "sha256-AhbssMeA+V47EBoOlc/DZ/LvVrBvLeqqqZJaDxF8INk=" + }, + "kotlin-gradle-plugin-api-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.9.0/kotlin-gradle-plugin-api-1.9.0.jar" + ], + "hash": "sha256-AhbssMeA+V47EBoOlc/DZ/LvVrBvLeqqqZJaDxF8INk=" + }, + "kotlin-gradle-plugin-api-1.9.0.module": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.9.0/kotlin-gradle-plugin-api-1.9.0.module" + ], + "hash": "sha256-Gu1WWijZE0KsWkuhRsKFal67xjkoXFKVUhefr8dhTds=" + } + }, + "org.jetbrains.kotlin:kotlin-gradle-plugins-bom:1.9.0": { + "kotlin-gradle-plugins-bom-1.9.0.module": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugins-bom/1.9.0/kotlin-gradle-plugins-bom-1.9.0.module" + ], + "hash": "sha256-/SufabguQ8tQnwhBsYvzxd99q18eC+oDT8CypZnW4pY=" + }, + "kotlin-gradle-plugins-bom-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugins-bom/1.9.0/kotlin-gradle-plugins-bom-1.9.0.pom" + ], + "hash": "sha256-XTmtkDDf0zsLrCn3UAAJzmKHYulP5h8BF3rhNL24D6E=" + } + }, + "org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.9.0": { + "kotlin-gradle-plugin-model-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.9.0/kotlin-gradle-plugin-model-1.9.0.jar" + ], + "hash": "sha256-/wWqtoizSnmSp+NfncTewlhD8Tqelwrv5W3T4SKghBU=" + }, + "kotlin-gradle-plugin-model-1.9.0.module": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.9.0/kotlin-gradle-plugin-model-1.9.0.module" + ], + "hash": "sha256-ZvS5FEcM80bgXQP4otWenHRvpu3PZMcS8XagiBqsPkk=" + } + }, + "org.jetbrains.kotlin:kotlin-tooling-core:1.9.0": { + "kotlin-tooling-core-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-tooling-core/1.9.0/kotlin-tooling-core-1.9.0.jar" + ], + "hash": "sha256-5TmiJCi5ysZ/dbLWHytuKnGDUNe7MYI8fcqJB/kJma4=" + }, + "kotlin-tooling-core-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-tooling-core/1.9.0/kotlin-tooling-core-1.9.0.pom" + ], + "hash": "sha256-KSbD/CFJWXAcjxYNjdyGn3s/pFKv3o3RdcjnwrvHBSI=" + } + }, + "org.jetbrains.kotlin:kotlin-sam-with-receiver:1.9.0": { + "kotlin-sam-with-receiver-1.9.0-gradle81.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-sam-with-receiver/1.9.0/kotlin-sam-with-receiver-1.9.0-gradle81.jar" + ], + "hash": "sha256-mK1U0XMRxg6FyGlDPV3TdpMTIDABJwCb5+nrsyH8xCs=" + }, + "kotlin-sam-with-receiver-1.9.0.module": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-sam-with-receiver/1.9.0/kotlin-sam-with-receiver-1.9.0.module" + ], + "hash": "sha256-GTPz8nsCrr/6LnvBmWN8TKg90xgHqjgwDLHh+jGsoiU=" + } + }, + "org.jetbrains.kotlin:kotlin-assignment:1.9.0": { + "kotlin-assignment-1.9.0-gradle81.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-assignment/1.9.0/kotlin-assignment-1.9.0-gradle81.jar" + ], + "hash": "sha256-mBdB+GlpwM4YQ1pcEJePJ3VGMxbOgqp/gmfsf2qfFNk=" + }, + "kotlin-assignment-1.9.0.module": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-assignment/1.9.0/kotlin-assignment-1.9.0.module" + ], + "hash": "sha256-kqBzm0y4NgSm3jddsKP+gTUDhZy8+aLtqZ++CXs8e9Y=" + } + }, + "org.jetbrains.kotlin:kotlin-gradle-plugin-annotations:1.9.0": { + "kotlin-gradle-plugin-annotations-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-annotations/1.9.0/kotlin-gradle-plugin-annotations-1.9.0.jar" + ], + "hash": "sha256-KiZbNbx8VYIUJukbajzU9LkWOKC8fIffz+TgX36IRzg=" + }, + "kotlin-gradle-plugin-annotations-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-annotations/1.9.0/kotlin-gradle-plugin-annotations-1.9.0.pom" + ], + "hash": "sha256-qjXuWp0dpZMV92nH/tsshwBWD1PFaAupKwsniBpKQnE=" + } + }, + "org.jetbrains.kotlin:kotlin-native-utils:1.9.0": { + "kotlin-native-utils-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-native-utils/1.9.0/kotlin-native-utils-1.9.0.jar" + ], + "hash": "sha256-D0gF93S/tcG20UXf5g09ILGu4ACJbOjs8+7/hM5EAjs=" + }, + "kotlin-native-utils-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-native-utils/1.9.0/kotlin-native-utils-1.9.0.pom" + ], + "hash": "sha256-Kazy3vkmve3Z6yBOx3Tnhq3Ek0EGqSlJAK81FVbn52o=" + } + }, + "org.jetbrains.kotlin:kotlin-util-io:1.9.0": { + "kotlin-util-io-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-io/1.9.0/kotlin-util-io-1.9.0.jar" + ], + "hash": "sha256-gdNtxt4/C+rwTDl6BrVoITujc6vO9Tlyt7gvYX1a9ws=" + }, + "kotlin-util-io-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-io/1.9.0/kotlin-util-io-1.9.0.pom" + ], + "hash": "sha256-BUBa+xn3tgbFKr6haJqi1ew9qQL+4teoV2lDOeSgQJQ=" + } + }, + "org.jetbrains.kotlin:kotlin-util-klib:1.9.0": { + "kotlin-util-klib-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-klib/1.9.0/kotlin-util-klib-1.9.0.jar" + ], + "hash": "sha256-wtxr820zabdzdVq4k3uX5Tmk1F04Fb7xm+36FUsS0xM=" + }, + "kotlin-util-klib-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-klib/1.9.0/kotlin-util-klib-1.9.0.pom" + ], + "hash": "sha256-acZHGaDgRjb2whMZ/lGKC1gieEu66P7YXmUfv6b4pFs=" + } + }, + "org.jetbrains.kotlin:kotlin-project-model:1.9.0": { + "kotlin-project-model-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-project-model/1.9.0/kotlin-project-model-1.9.0.jar" + ], + "hash": "sha256-rgk26bTGkh8D73eTYcrLu3XtKyIQR5+S9l8cushuNAw=" + }, + "kotlin-project-model-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-project-model/1.9.0/kotlin-project-model-1.9.0.pom" + ], + "hash": "sha256-6sHGTGAMYAJ7jmjfrTogPEFbn6IkWB1oz6Xnc+hWa3g=" + } + }, + "org.jetbrains.kotlin:kotlin-gradle-plugin-idea:1.9.0": { + "kotlin-gradle-plugin-idea-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.9.0/kotlin-gradle-plugin-idea-1.9.0.jar" + ], + "hash": "sha256-C7JszuNyr7m1hPKFfofMLz9TK2Kk9/pFdVjzr8Or6ZU=" + }, + "kotlin-gradle-plugin-idea-1.9.0.module": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.9.0/kotlin-gradle-plugin-idea-1.9.0.module" + ], + "hash": "sha256-pVg82bC0AS6VWtlhn7kBe1saosJRsFltr1M0kExcpls=" + } + }, + "org.jetbrains.kotlin:kotlin-gradle-plugin-idea-proto:1.9.0": { + "kotlin-gradle-plugin-idea-proto-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea-proto/1.9.0/kotlin-gradle-plugin-idea-proto-1.9.0.jar" + ], + "hash": "sha256-54mY6iK81fVtE5gszBJMnHM3vRUHVMvcivKhSNdslwA=" + }, + "kotlin-gradle-plugin-idea-proto-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea-proto/1.9.0/kotlin-gradle-plugin-idea-proto-1.9.0.pom" + ], + "hash": "sha256-QeElaFOKOjQHBMlww6T2D/WAH/3OQlymjKLAtHIhclA=" + } + }, + "org.jetbrains.kotlin:kotlin-klib-commonizer-api:1.9.0": { + "kotlin-klib-commonizer-api-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.9.0/kotlin-klib-commonizer-api-1.9.0.jar" + ], + "hash": "sha256-hd4ulysLtvRSjB90j0PEhmMUX8hTnsqWwT0bwNo/k10=" + }, + "kotlin-klib-commonizer-api-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.9.0/kotlin-klib-commonizer-api-1.9.0.pom" + ], + "hash": "sha256-hE+SCI/0j4v64lYh4yStw1d5CM9lD0/bJWlhC4+vaz4=" + } + }, + "org.jetbrains.kotlin:kotlin-build-tools-api:1.9.0": { + "kotlin-build-tools-api-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-build-tools-api/1.9.0/kotlin-build-tools-api-1.9.0.jar" + ], + "hash": "sha256-0ZyavegKnPQtJezJLLEUjtOhXu2yZy2qHkZubaWQ7sY=" + }, + "kotlin-build-tools-api-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-build-tools-api/1.9.0/kotlin-build-tools-api-1.9.0.pom" + ], + "hash": "sha256-iIFxmCZbm8BrPzSTWyv2qpj0gA7OvBzOQREN70m3pCE=" + } + }, + "org.jetbrains.kotlin:kotlin-compiler-embeddable:1.9.0": { + "kotlin-compiler-embeddable-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.9.0/kotlin-compiler-embeddable-1.9.0.jar" + ], + "hash": "sha256-lTtQaR103SGf8/ZkRnDD5UnYfN/AphVPFgKmoKXf43M=" + }, + "kotlin-compiler-embeddable-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.9.0/kotlin-compiler-embeddable-1.9.0.pom" + ], + "hash": "sha256-7jyHHO39bM9A0ESUQJbihlXeL5NF2ET+7GPMqcXkt8w=" + } + }, + "org.jetbrains.kotlin:kotlin-daemon-embeddable:1.9.0": { + "kotlin-daemon-embeddable-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.9.0/kotlin-daemon-embeddable-1.9.0.jar" + ], + "hash": "sha256-lDGCoTfs1A5ikFjaUtszbO6bZm+AmWtlWELyCmNz35o=" + }, + "kotlin-daemon-embeddable-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.9.0/kotlin-daemon-embeddable-1.9.0.pom" + ], + "hash": "sha256-OOMsu5GFenIGy/3cON1O4L5mX0CgEV/21NF348f4kq8=" + } + }, + "org.jetbrains.intellij.deps:trove4j:1.0.20200330": { + "trove4j-1.0.20200330.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.jar" + ], + "hash": "sha256-xf1yW/+rUYRr88d9sTg8YKquv+G3/i8A0j/ht98KQ50=" + }, + "trove4j-1.0.20200330.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.pom" + ], + "hash": "sha256-h3IcuqZaPJfYsbqdIHhA8WTJ/jh1n8nqEP/iZWX40+k=" + } + }, + "org.jetbrains.kotlin:kotlin-android-extensions:1.9.0": { + "kotlin-android-extensions-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-android-extensions/1.9.0/kotlin-android-extensions-1.9.0.jar" + ], + "hash": "sha256-IGdbuyp7aYKnFEUYpRi5qJZfkK6JuMmHiJgBIkSh6jM=" + }, + "kotlin-android-extensions-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-android-extensions/1.9.0/kotlin-android-extensions-1.9.0.pom" + ], + "hash": "sha256-WOHIg3JukUaVIDV95u0Xw/mSnI4IsRdKJ6OtbsDrzVI=" + } + }, + "org.jetbrains.kotlin:kotlin-compiler-runner:1.9.0": { + "kotlin-compiler-runner-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-runner/1.9.0/kotlin-compiler-runner-1.9.0.jar" + ], + "hash": "sha256-BbWlXUlJFhpxT838ZKXwTYejZMm73IZBs7t6VVfkPqo=" + }, + "kotlin-compiler-runner-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-runner/1.9.0/kotlin-compiler-runner-1.9.0.pom" + ], + "hash": "sha256-GIN9BlVntn5bzy4wTYWm4rbSRDz4En9AdnNKTo3yo2E=" + } + }, + "org.jetbrains.kotlin:kotlin-daemon-client:1.9.0": { + "kotlin-daemon-client-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-client/1.9.0/kotlin-daemon-client-1.9.0.jar" + ], + "hash": "sha256-WoyXfn3H8N4tka5Yva3CBBXe9M9dST5aGD+WxZeZAyA=" + }, + "kotlin-daemon-client-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-client/1.9.0/kotlin-daemon-client-1.9.0.pom" + ], + "hash": "sha256-sv50dBgjzM6JMXCWkg3LnOXBa460Z5jTn9jmdwPFidc=" + } + }, + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.0": { + "kotlinx-coroutines-core-jvm-1.5.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.5.0/kotlinx-coroutines-core-jvm-1.5.0.jar" + ], + "hash": "sha256-eNbMcTX4TWkv83Uvz9H6G74JQNffcGUuTx6u7Ax4r7s=" + }, + "kotlinx-coroutines-core-jvm-1.5.0.module": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.5.0/kotlinx-coroutines-core-jvm-1.5.0.module" + ], + "hash": "sha256-yIXdAoEHbFhDgm3jF+PLzcPYhZ2+71OuHPrNG5xg+W4=" + } + }, + "org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.9.0": { + "kotlin-scripting-compiler-embeddable-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.9.0/kotlin-scripting-compiler-embeddable-1.9.0.jar" + ], + "hash": "sha256-Rp3RIGiVipevzhGIoBRFVM3tZ95aGqC/XKUwOfKdizY=" + }, + "kotlin-scripting-compiler-embeddable-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.9.0/kotlin-scripting-compiler-embeddable-1.9.0.pom" + ], + "hash": "sha256-UJ5ikUwwvT43GcDgLk5Df8vxkRa4ouZYSPbUbFTsXJ4=" + } + }, + "org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.9.0": { + "kotlin-scripting-compiler-impl-embeddable-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.9.0/kotlin-scripting-compiler-impl-embeddable-1.9.0.jar" + ], + "hash": "sha256-ZcUlbiyPvdpCbAMobmomgmfXEu+V7C05yVKSlXN4sE0=" + }, + "kotlin-scripting-compiler-impl-embeddable-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.9.0/kotlin-scripting-compiler-impl-embeddable-1.9.0.pom" + ], + "hash": "sha256-zaYp8KgbqcAKM95QJ/D4/7+fC45E5BlwNHdmu4WLTmM=" + } + }, + "org.jetbrains.kotlin:kotlin-scripting-common:1.9.0": { + "kotlin-scripting-common-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-common/1.9.0/kotlin-scripting-common-1.9.0.jar" + ], + "hash": "sha256-KFxBwO7tWaDn3LGIuJ+BVBR/vLvVNUcc9piWzNonP4Q=" + }, + "kotlin-scripting-common-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-common/1.9.0/kotlin-scripting-common-1.9.0.pom" + ], + "hash": "sha256-C/MG5PRe6xrDAk4pnUybcL4J7OmsAOcLL/mLPtQA8wc=" + } + }, + "org.jetbrains.kotlin:kotlin-scripting-jvm:1.9.0": { + "kotlin-scripting-jvm-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.9.0/kotlin-scripting-jvm-1.9.0.jar" + ], + "hash": "sha256-Zp3SvGBBjgdRU/2K2NllvlaetlwvMIOIyxEDud8TUVk=" + }, + "kotlin-scripting-jvm-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.9.0/kotlin-scripting-jvm-1.9.0.pom" + ], + "hash": "sha256-Ymj4BVjTX9qSRruneTKWkrlNWJWWVQfL6KhIkSxQ5yo=" + } + }, + "org.jetbrains.kotlin:kotlin-reflect:1.9.0": { + "kotlin-reflect-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-reflect/1.9.0/kotlin-reflect-1.9.0.jar" + ], + "hash": "sha256-IHAVm+UU6o6jziyLHueZPm/2CpNWWimfIAYpqn339YE=" + }, + "kotlin-reflect-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-reflect/1.9.0/kotlin-reflect-1.9.0.pom" + ], + "hash": "sha256-hXFWVnbRiXIEcTBs7ppV2RbAgDgvNabaaBk6x7EvTNs=" + } + }, + "com.gradle.publish:plugin-publish-plugin:1.2.1": { + "plugin-publish-plugin-1.2.1.jar": { + "urls": [ + "https://plugins.gradle.org/m2/com/gradle/publish/plugin-publish-plugin/1.2.1/plugin-publish-plugin-1.2.1.jar" + ], + "hash": "sha256-KY8MLpeVMhcaBaQWAyY3M7ZfiRE9ToCczQ4mmQFJ3hg=" + }, + "plugin-publish-plugin-1.2.1.module": { + "urls": [ + "https://plugins.gradle.org/m2/com/gradle/publish/plugin-publish-plugin/1.2.1/plugin-publish-plugin-1.2.1.module" + ], + "hash": "sha256-w98uuag1ZdO2MVDYa0344o9mG1XOzdRJJ+RpMxA2yxk=" + } + }, + "org.apache.maven:maven-model:3.6.3": { + "maven-model-3.6.3.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/apache/maven/maven-model/3.6.3/maven-model-3.6.3.jar" + ], + "hash": "sha256-F87x9Y4UbvDX2elrO5LZih1v19KzKIulOOj/Hg2RYM8=" + }, + "maven-model-3.6.3.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/apache/maven/maven-model/3.6.3/maven-model-3.6.3.pom" + ], + "hash": "sha256-fHIOjLA9KFxxzW4zTZyeWWBivdMQ7grRX1xHmpkxVPA=" + } + }, + "org.jetbrains.kotlin:kotlin-script-runtime:1.9.0": { + "kotlin-script-runtime-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-script-runtime/1.9.0/kotlin-script-runtime-1.9.0.jar" + ], + "hash": "sha256-2E0MykEFD6wqlS0RBEc8Mpr/BMULNxMuV1SiCYCa3Z8=" + }, + "kotlin-script-runtime-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-script-runtime/1.9.0/kotlin-script-runtime-1.9.0.pom" + ], + "hash": "sha256-FNwHhdGUFP7sEgI91z64DIPQeIC3PlS48IqHj0I9seY=" + } + }, + "org.jetbrains.kotlin:kotlin-reflect:1.6.10": { + "kotlin-reflect-1.6.10.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-reflect/1.6.10/kotlin-reflect-1.6.10.jar" + ], + "hash": "sha256-MnesECrheq0QpVq+x1/1aWyNEJeQOWQ0tJbnUIeFQgM=" + }, + "kotlin-reflect-1.6.10.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-reflect/1.6.10/kotlin-reflect-1.6.10.pom" + ], + "hash": "sha256-V5BVJCdKAK4CiqzMJyg/a8WSWpNKBGwcxdBsjuTW1ak=" + } + }, + "org.jetbrains.kotlin:kotlin-sam-with-receiver-compiler-plugin-embeddable:1.9.0": { + "kotlin-sam-with-receiver-compiler-plugin-embeddable-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-sam-with-receiver-compiler-plugin-embeddable/1.9.0/kotlin-sam-with-receiver-compiler-plugin-embeddable-1.9.0.jar" + ], + "hash": "sha256-o7OlA4sNEybfGz/lvyCmaQnt1C3qa2P3BgCm8k/0VYw=" + }, + "kotlin-sam-with-receiver-compiler-plugin-embeddable-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-sam-with-receiver-compiler-plugin-embeddable/1.9.0/kotlin-sam-with-receiver-compiler-plugin-embeddable-1.9.0.pom" + ], + "hash": "sha256-WdgiTXgRi2RAwdRsCRzwLOWSnQaTU0hZnxP9wrmoU88=" + } + }, + "org.jetbrains.kotlin:kotlin-assignment-compiler-plugin-embeddable:1.9.0": { + "kotlin-assignment-compiler-plugin-embeddable-1.9.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-assignment-compiler-plugin-embeddable/1.9.0/kotlin-assignment-compiler-plugin-embeddable-1.9.0.jar" + ], + "hash": "sha256-MBY6DUXnN9gHW0kI0PCv8DXvqGa+iFIvQ37Jbg43KZQ=" + }, + "kotlin-assignment-compiler-plugin-embeddable-1.9.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-assignment-compiler-plugin-embeddable/1.9.0/kotlin-assignment-compiler-plugin-embeddable-1.9.0.pom" + ], + "hash": "sha256-HDfsoLIO1JYF6lVsonWq8eyZUaKZge4TNxZYP2pD4J8=" + } + } +} \ No newline at end of file diff --git a/fixtures/golden/dependency/classifier.groovy.json b/fixtures/golden/dependency/classifier.groovy.json new file mode 100644 index 0000000..c4ee874 --- /dev/null +++ b/fixtures/golden/dependency/classifier.groovy.json @@ -0,0 +1,16 @@ +{ + "com.badlogicgames.gdx:gdx-platform:1.9.9": { + "gdx-platform-1.9.9-natives-desktop.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/badlogicgames/gdx/gdx-platform/1.9.9/gdx-platform-1.9.9-natives-desktop.jar" + ], + "hash": "sha256-e8c9VPpFH+LeJU6PgmCkOb/jutOxFnO6LPMaTxL2hU8=" + }, + "gdx-platform-1.9.9.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/badlogicgames/gdx/gdx-platform/1.9.9/gdx-platform-1.9.9.pom" + ], + "hash": "sha256-SWnDZyJaErav4Z4sA+D1WA3U1aQOSR64sd8+cQzofSY=" + } + } +} \ No newline at end of file diff --git a/fixtures/golden/dependency/classifier.kotlin.json b/fixtures/golden/dependency/classifier.kotlin.json new file mode 100644 index 0000000..c4ee874 --- /dev/null +++ b/fixtures/golden/dependency/classifier.kotlin.json @@ -0,0 +1,16 @@ +{ + "com.badlogicgames.gdx:gdx-platform:1.9.9": { + "gdx-platform-1.9.9-natives-desktop.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/badlogicgames/gdx/gdx-platform/1.9.9/gdx-platform-1.9.9-natives-desktop.jar" + ], + "hash": "sha256-e8c9VPpFH+LeJU6PgmCkOb/jutOxFnO6LPMaTxL2hU8=" + }, + "gdx-platform-1.9.9.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/badlogicgames/gdx/gdx-platform/1.9.9/gdx-platform-1.9.9.pom" + ], + "hash": "sha256-SWnDZyJaErav4Z4sA+D1WA3U1aQOSR64sd8+cQzofSY=" + } + } +} \ No newline at end of file diff --git a/fixtures/golden/dependency/maven-bom.kotlin.json b/fixtures/golden/dependency/maven-bom.kotlin.json new file mode 100644 index 0000000..9521858 --- /dev/null +++ b/fixtures/golden/dependency/maven-bom.kotlin.json @@ -0,0 +1,38 @@ +{ + "io.micrometer:micrometer-bom:1.5.1": { + "micrometer-bom-1.5.1.pom": { + "urls": [ + "file:/home/tad/proj/gradle2nix/fixtures/repositories/m2/io/micrometer/micrometer-bom/1.5.1/micrometer-bom-1.5.1.pom" + ], + "hash": "sha256-K/qF6ds8ck5sWvelJBYk+w+K04oQpT/4BtY57WVLRUI=" + } + }, + "io.micrometer:micrometer-core:1.5.1": { + "micrometer-core-1.5.1.jar": { + "urls": [ + "file:/home/tad/proj/gradle2nix/fixtures/repositories/m2/io/micrometer/micrometer-core/1.5.1/micrometer-core-1.5.1.jar" + ], + "hash": "sha256-DtgVYBDVGDBWMwSfeKC6O+fwqd+N2q4eTizJgQ1wfI8=" + }, + "micrometer-core-1.5.1.pom": { + "urls": [ + "file:/home/tad/proj/gradle2nix/fixtures/repositories/m2/io/micrometer/micrometer-core/1.5.1/micrometer-core-1.5.1.pom" + ], + "hash": "sha256-Cb4KaUHaOvdOz7VpDax6kJKuT2KWY5Ci73foX2xl6xw=" + } + }, + "org.hdrhistogram:HdrHistogram:2.1.12": { + "HdrHistogram-2.1.12.jar": { + "urls": [ + "file:/home/tad/proj/gradle2nix/fixtures/repositories/m2/org/hdrhistogram/HdrHistogram/2.1.12/HdrHistogram-2.1.12.jar" + ], + "hash": "sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=" + }, + "HdrHistogram-2.1.12.pom": { + "urls": [ + "file:/home/tad/proj/gradle2nix/fixtures/repositories/m2/org/hdrhistogram/HdrHistogram/2.1.12/HdrHistogram-2.1.12.pom" + ], + "hash": "sha256-f7PnkMFU0bXiMXC7jL9/cO8ICa8XIp8dywENd5llEIA=" + } + } +} \ No newline at end of file diff --git a/fixtures/golden/dependency/snapshot-dynamic.groovy.json b/fixtures/golden/dependency/snapshot-dynamic.groovy.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/fixtures/golden/dependency/snapshot-dynamic.groovy.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/fixtures/golden/dependency/snapshot-dynamic.kotlin.json b/fixtures/golden/dependency/snapshot-dynamic.kotlin.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/fixtures/golden/dependency/snapshot-dynamic.kotlin.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/fixtures/golden/dependency/snapshot-redirect.groovy.json b/fixtures/golden/dependency/snapshot-redirect.groovy.json new file mode 100644 index 0000000..cf94179 --- /dev/null +++ b/fixtures/golden/dependency/snapshot-redirect.groovy.json @@ -0,0 +1,16 @@ +{ + "com.github.anuken:packr:-SNAPSHOT:packr-1.2-g034efe5-114": { + "packr--SNAPSHOT.pom": { + "urls": [ + "https://jitpack.io/com/github/anuken/packr/-SNAPSHOT/packr--SNAPSHOT.pom" + ], + "hash": "sha256-xP28J7blX1IzuJxD4u/wy1ZbwAT5RAajBcpBWs1fAxU=" + }, + "packr--SNAPSHOT.jar": { + "urls": [ + "https://jitpack.io/com/github/anuken/packr/-SNAPSHOT/packr--SNAPSHOT.jar" + ], + "hash": "sha256-XrfVZLc7efr2n3Bz6mOw8DkRI0T8rU8B/MKUMVDl71w=" + } + } +} \ No newline at end of file diff --git a/fixtures/golden/dependency/snapshot.groovy.json b/fixtures/golden/dependency/snapshot.groovy.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/fixtures/golden/dependency/snapshot.groovy.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/fixtures/golden/dependency/snapshot.kotlin.json b/fixtures/golden/dependency/snapshot.kotlin.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/fixtures/golden/dependency/snapshot.kotlin.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/fixtures/golden/integration/settings-buildscript.groovy.json b/fixtures/golden/integration/settings-buildscript.groovy.json new file mode 100644 index 0000000..61a1815 --- /dev/null +++ b/fixtures/golden/integration/settings-buildscript.groovy.json @@ -0,0 +1,128 @@ +{ + "gradle.plugin.net.vivin:gradle-semantic-build-versioning:4.0.0": { + "gradle-semantic-build-versioning-4.0.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/gradle/plugin/net/vivin/gradle-semantic-build-versioning/4.0.0/gradle-semantic-build-versioning-4.0.0.jar" + ], + "hash": "sha256-UTjmfOjgGUN4ALk8n2+dD8vr763Jb7xOvAl1yZomHvg=" + }, + "gradle-semantic-build-versioning-4.0.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/gradle/plugin/net/vivin/gradle-semantic-build-versioning/4.0.0/gradle-semantic-build-versioning-4.0.0.pom" + ], + "hash": "sha256-TygodBYH7RAtletfGJ1JbHhA7UY6zqifHlGmBWdxTvc=" + } + }, + "org.eclipse.jgit:org.eclipse.jgit:4.8.0.201706111038-r": { + "org.eclipse.jgit-4.8.0.201706111038-r.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/eclipse/jgit/org.eclipse.jgit/4.8.0.201706111038-r/org.eclipse.jgit-4.8.0.201706111038-r.jar" + ], + "hash": "sha256-SdkS6NXM4N0I3KPTkBiduGkqj34zY8274YJYFGIACro=" + }, + "org.eclipse.jgit-4.8.0.201706111038-r.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/eclipse/jgit/org.eclipse.jgit/4.8.0.201706111038-r/org.eclipse.jgit-4.8.0.201706111038-r.pom" + ], + "hash": "sha256-pVap9a38avSbKhLnLcPNfkPbj9whbA81iFlyovWton0=" + } + }, + "com.jcraft:jsch:0.1.54": { + "jsch-0.1.54.jar": { + "urls": [ + "https://plugins.gradle.org/m2/com/jcraft/jsch/0.1.54/jsch-0.1.54.jar" + ], + "hash": "sha256-kusnOjMWdiR4/dT+A6DOGELFb0lsnBL+EjXbgEUOH9s=" + }, + "jsch-0.1.54.pom": { + "urls": [ + "https://plugins.gradle.org/m2/com/jcraft/jsch/0.1.54/jsch-0.1.54.pom" + ], + "hash": "sha256-q49RIDm+f2riDhjnQ7Sp2KIJWElEMZF9pYrlqu+KNHg=" + } + }, + "com.googlecode.javaewah:JavaEWAH:1.1.6": { + "JavaEWAH-1.1.6.jar": { + "urls": [ + "https://plugins.gradle.org/m2/com/googlecode/javaewah/JavaEWAH/1.1.6/JavaEWAH-1.1.6.jar" + ], + "hash": "sha256-941EoeOHfxznSLSoXfUXHl6Omlw8b2O7kAPbb4TM6VI=" + }, + "JavaEWAH-1.1.6.pom": { + "urls": [ + "https://plugins.gradle.org/m2/com/googlecode/javaewah/JavaEWAH/1.1.6/JavaEWAH-1.1.6.pom" + ], + "hash": "sha256-f0/5GbHuF783duBYo/IOYXPbI6XkTPLRB+x1cMGGq/A=" + } + }, + "org.apache.httpcomponents:httpclient:4.3.6": { + "httpclient-4.3.6.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/apache/httpcomponents/httpclient/4.3.6/httpclient-4.3.6.jar" + ], + "hash": "sha256-eYONnq73PU+FLGOkgIMMOi1LWQ8Ks66BWkiUY+RxQAQ=" + }, + "httpclient-4.3.6.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/apache/httpcomponents/httpclient/4.3.6/httpclient-4.3.6.pom" + ], + "hash": "sha256-0CY09hMekUlhwCqoNnEeuscnBLJ+JsW9Iju62JsbZMM=" + } + }, + "org.apache.httpcomponents:httpcore:4.3.3": { + "httpcore-4.3.3.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/apache/httpcomponents/httpcore/4.3.3/httpcore-4.3.3.jar" + ], + "hash": "sha256-UoXegK8WUcSJMTuRqfQMZaTNy2s73nFvzAKNFoaaWpM=" + }, + "httpcore-4.3.3.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/apache/httpcomponents/httpcore/4.3.3/httpcore-4.3.3.pom" + ], + "hash": "sha256-tCf3z2fHWk4/niEI01v0UwNXPBRex3j8rc/6zvF6EmQ=" + } + }, + "commons-logging:commons-logging:1.1.3": { + "commons-logging-1.1.3.jar": { + "urls": [ + "https://plugins.gradle.org/m2/commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar" + ], + "hash": "sha256-cJA/b8gumQjI2p8gRD9h2Q8IcKMSZCmR/oRioLk5F4Q=" + }, + "commons-logging-1.1.3.pom": { + "urls": [ + "https://plugins.gradle.org/m2/commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.pom" + ], + "hash": "sha256-MlCsOsa9YO0GMfXNAzUDKymT1j5AWmrgVV0np+SGWEk=" + } + }, + "commons-codec:commons-codec:1.6": { + "commons-codec-1.6.jar": { + "urls": [ + "https://plugins.gradle.org/m2/commons-codec/commons-codec/1.6/commons-codec-1.6.jar" + ], + "hash": "sha256-VLNOlBuOFBS9PkDXNu/TSBdy3CbbMpb2qkXOyfYgPYY=" + }, + "commons-codec-1.6.pom": { + "urls": [ + "https://plugins.gradle.org/m2/commons-codec/commons-codec/1.6/commons-codec-1.6.pom" + ], + "hash": "sha256-oG410//zprgT2UiU6/PkmPlUDIZMWzmueDkH46bHKIk=" + } + }, + "org.slf4j:slf4j-api:1.7.2": { + "slf4j-api-1.7.2.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/slf4j/slf4j-api/1.7.2/slf4j-api-1.7.2.jar" + ], + "hash": "sha256-O654m0ATM7Kh0WA7f6Vz4ZkIYoGRcHID9utwjN7iwFI=" + }, + "slf4j-api-1.7.2.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/slf4j/slf4j-api/1.7.2/slf4j-api-1.7.2.pom" + ], + "hash": "sha256-LqynGv4KFRb0q9jp/5B4ONJo84yBw6VCzOjX87h8XUw=" + } + } +} \ No newline at end of file diff --git a/fixtures/golden/ivy/basic.kotlin.json b/fixtures/golden/ivy/basic.kotlin.json new file mode 100644 index 0000000..4e61434 --- /dev/null +++ b/fixtures/golden/ivy/basic.kotlin.json @@ -0,0 +1,30 @@ +{ + "org.opendof.core-java:dof-cipher-sms4:1.0": { + "dof-cipher-sms4-1.0.jar": { + "urls": [ + "https://asset.opendof.org/artifact/org.opendof.core-java/dof-cipher-sms4/1.0/dof-cipher-sms4-1.0.jar" + ], + "hash": "sha256-/Joo51NA6nBPEwFuFcnDc10JQZDE8P3jF3P4gl0vpMA=" + }, + "ivy-1.0.xml": { + "urls": [ + "https://asset.opendof.org/ivy2/org.opendof.core-java/dof-cipher-sms4/1.0/ivy.xml" + ], + "hash": "sha256-rh+pQpXqPP/cmBD8slvwMrKlWCUb3JNzW3l58hd7oJ8=" + } + }, + "org.opendof.core-java:dof-oal:7.0.2": { + "dof-oal-7.0.2.jar": { + "urls": [ + "https://asset.opendof.org/artifact/org.opendof.core-java/dof-oal/7.0.2/dof-oal-7.0.2.jar" + ], + "hash": "sha256-u+FUhQGBA8MRl28mXMTSnZ2HY2ysPHq7h9lANmHBK40=" + }, + "ivy-7.0.2.xml": { + "urls": [ + "https://asset.opendof.org/ivy2/org.opendof.core-java/dof-oal/7.0.2/ivy.xml" + ], + "hash": "sha256-KZoUVyoDcfH/B/9V1SVqNiA/XIb3zlwoJkjb/jD+xig=" + } + } +} \ No newline at end of file diff --git a/fixtures/golden/plugin/resolves-from-default-repo.groovy.json b/fixtures/golden/plugin/resolves-from-default-repo.groovy.json new file mode 100644 index 0000000..58789dd --- /dev/null +++ b/fixtures/golden/plugin/resolves-from-default-repo.groovy.json @@ -0,0 +1,494 @@ +{ + "org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.7.21": { + "org.jetbrains.kotlin.jvm.gradle.plugin-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.7.21/org.jetbrains.kotlin.jvm.gradle.plugin-1.7.21.pom" + ], + "hash": "sha256-18S+c5nTziimR77ivh3nCwUdpLqoz9X4KYNDJ2UKD30=" + } + }, + "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.21": { + "kotlin-gradle-plugin-1.7.21-gradle71.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin/1.7.21/kotlin-gradle-plugin-1.7.21-gradle71.jar" + ], + "hash": "sha256-P12cqfSxiGOZjcVpNIk9m1ICRRzucJ+uuXbI+rI2cyI=" + }, + "kotlin-gradle-plugin-1.7.21.module": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin/1.7.21/kotlin-gradle-plugin-1.7.21.module" + ], + "hash": "sha256-j6I2KYtJBynes0XjG8ZPKSj3wbXxwjH8ZtvINlnBZ+E=" + } + }, + "org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.7.21": { + "kotlin-gradle-plugin-api-1.7.21-gradle71.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.7.21/kotlin-gradle-plugin-api-1.7.21-gradle71.jar" + ], + "hash": "sha256-rflytT2LY7s2jZA88y6bB+pTZW6PnaXxDfuv03gxviE=" + }, + "kotlin-gradle-plugin-api-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.7.21/kotlin-gradle-plugin-api-1.7.21.jar" + ], + "hash": "sha256-rflytT2LY7s2jZA88y6bB+pTZW6PnaXxDfuv03gxviE=" + }, + "kotlin-gradle-plugin-api-1.7.21.module": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.7.21/kotlin-gradle-plugin-api-1.7.21.module" + ], + "hash": "sha256-zGXnGhweng0JaG9cpJGORShIY1q7VCl15HwYlnw6A10=" + } + }, + "org.jetbrains.kotlin:kotlin-native-utils:1.7.21": { + "kotlin-native-utils-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-native-utils/1.7.21/kotlin-native-utils-1.7.21.jar" + ], + "hash": "sha256-k1KYF/2Nj9hlItZqqtyr0UKhcueMz+uUnNKJ40xw+Qs=" + }, + "kotlin-native-utils-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-native-utils/1.7.21/kotlin-native-utils-1.7.21.pom" + ], + "hash": "sha256-CEYFdUhagoAZC0g8H3fyCk063IegIXTzDuxVdNm65FY=" + } + }, + "org.jetbrains.kotlin:kotlin-util-io:1.7.21": { + "kotlin-util-io-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-io/1.7.21/kotlin-util-io-1.7.21.jar" + ], + "hash": "sha256-7MKI4AQqAUdgOeILbOXgaRj+8fic+J9V39KO8Xwm800=" + }, + "kotlin-util-io-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-io/1.7.21/kotlin-util-io-1.7.21.pom" + ], + "hash": "sha256-ziTM1kPWW+8Cey9uINCnkhdq29ug2eVVmS5CR6Y3Ne8=" + } + }, + "org.jetbrains.kotlin:kotlin-project-model:1.7.21": { + "kotlin-project-model-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-project-model/1.7.21/kotlin-project-model-1.7.21.jar" + ], + "hash": "sha256-4htTvrj3SxM6Y4mClPSlfcSiKJvoVfZrD5rosVYjFT8=" + }, + "kotlin-project-model-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-project-model/1.7.21/kotlin-project-model-1.7.21.pom" + ], + "hash": "sha256-JQfT7SKoHyssNSxMUOY1MivHEQClFQJN0NtQRifJ8Bs=" + } + }, + "org.jetbrains.kotlin:kotlin-tooling-core:1.7.21": { + "kotlin-tooling-core-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-tooling-core/1.7.21/kotlin-tooling-core-1.7.21.jar" + ], + "hash": "sha256-N5fxg1NC+8EuycHU+YMyugKCkaMyUakHySJ9j9lK7kg=" + }, + "kotlin-tooling-core-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-tooling-core/1.7.21/kotlin-tooling-core-1.7.21.pom" + ], + "hash": "sha256-tw2g1Eorhw7Lz85ZcMMOOOLs3htfQqHdRC0TA5gSKUY=" + } + }, + "org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.7.21": { + "kotlin-gradle-plugin-model-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.7.21/kotlin-gradle-plugin-model-1.7.21.jar" + ], + "hash": "sha256-FNP/F7o8tMi+uK3297QFB4gTS4kbsTyr5yPIwQ0dDhg=" + }, + "kotlin-gradle-plugin-model-1.7.21.module": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.7.21/kotlin-gradle-plugin-model-1.7.21.module" + ], + "hash": "sha256-kCJoZCp1guVF4xgQnjdIw3WxOLCKFVuBX2yAi7vuR7U=" + } + }, + "org.jetbrains.kotlin:kotlin-gradle-plugin-idea:1.7.21": { + "kotlin-gradle-plugin-idea-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.7.21/kotlin-gradle-plugin-idea-1.7.21.jar" + ], + "hash": "sha256-C1dqyzeBqctWEKphxbev3zKQ/C2digzUv+FTe4dcReY=" + }, + "kotlin-gradle-plugin-idea-1.7.21.module": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.7.21/kotlin-gradle-plugin-idea-1.7.21.module" + ], + "hash": "sha256-ygHy2JJMcpaXMax+oVbwi7GP60LDEAClIj2dwW1ZuTg=" + } + }, + "org.jetbrains.kotlin:kotlin-gradle-plugin-idea-proto:1.7.21": { + "kotlin-gradle-plugin-idea-proto-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea-proto/1.7.21/kotlin-gradle-plugin-idea-proto-1.7.21.jar" + ], + "hash": "sha256-NZhwZybLzo0oE05oiZw9WAv3LH6/kJcUHY28rtgnmHg=" + }, + "kotlin-gradle-plugin-idea-proto-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea-proto/1.7.21/kotlin-gradle-plugin-idea-proto-1.7.21.pom" + ], + "hash": "sha256-PRwDYK9odF8qAyoMAYR//Pnriq1wa/ZZydhAoYTsXyM=" + } + }, + "org.jetbrains.kotlin:kotlin-util-klib:1.7.21": { + "kotlin-util-klib-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-klib/1.7.21/kotlin-util-klib-1.7.21.jar" + ], + "hash": "sha256-UgkkU0RkIN+7h4BN6s6yGfVI53fm3xK35wRKOmaHEgs=" + }, + "kotlin-util-klib-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-klib/1.7.21/kotlin-util-klib-1.7.21.pom" + ], + "hash": "sha256-D8d7J3Rc+kzuX+AA5tEpmtSUT3rMB4A7u8ws0rAT3oU=" + } + }, + "org.jetbrains.kotlin:kotlin-klib-commonizer-api:1.7.21": { + "kotlin-klib-commonizer-api-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.7.21/kotlin-klib-commonizer-api-1.7.21.jar" + ], + "hash": "sha256-MOGWrbAAH9F7ZgNe2QcNPw5Hui0ycTt1wwPGt7e3FeI=" + }, + "kotlin-klib-commonizer-api-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.7.21/kotlin-klib-commonizer-api-1.7.21.pom" + ], + "hash": "sha256-so6g3vy5lNH7U6e7olh9J0DG0mAXk2UglP1ox0Ul0CA=" + } + }, + "org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.21": { + "kotlin-compiler-embeddable-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.jar", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.jar" + ], + "hash": "sha256-Ty5JK8x5XgaA4/h67qGtrp8wbK9SBAuUpvoPiP2skvk=" + }, + "kotlin-compiler-embeddable-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.pom", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.pom" + ], + "hash": "sha256-CwIzMip2MO/eEzUmjkYSPw1tNjg5gg/TfE7Lbv+njjs=" + } + }, + "org.jetbrains.kotlin:kotlin-daemon-embeddable:1.7.21": { + "kotlin-daemon-embeddable-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.jar", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.jar" + ], + "hash": "sha256-A+bwJUNSJIlOSe5e2EfLCwtKh540z6uQ1wzakmKnV00=" + }, + "kotlin-daemon-embeddable-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.pom", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.pom" + ], + "hash": "sha256-vB3pwgh7ouTlQQF6i66PQF7IAKGK5MJH6R8rVedh5kk=" + } + }, + "org.jetbrains.intellij.deps:trove4j:1.0.20200330": { + "trove4j-1.0.20200330.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.jar", + "https://repo.maven.apache.org/maven2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.jar" + ], + "hash": "sha256-xf1yW/+rUYRr88d9sTg8YKquv+G3/i8A0j/ht98KQ50=" + }, + "trove4j-1.0.20200330.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.pom", + "https://repo.maven.apache.org/maven2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.pom" + ], + "hash": "sha256-h3IcuqZaPJfYsbqdIHhA8WTJ/jh1n8nqEP/iZWX40+k=" + } + }, + "net.java.dev.jna:jna:5.6.0": { + "jna-5.6.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.jar", + "https://repo.maven.apache.org/maven2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.jar" + ], + "hash": "sha256-VVfiNaiqL5dm1dxgnWeUjyqIMsLXls6p7x1svgs7fq8=" + }, + "jna-5.6.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.pom", + "https://repo.maven.apache.org/maven2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.pom" + ], + "hash": "sha256-X+gbAlWXjyRhbTexBgi3lJil8wc+HZsgONhzaoMfJgg=" + } + }, + "org.jetbrains.kotlin:kotlin-annotation-processing-gradle:1.7.21": { + "kotlin-annotation-processing-gradle-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.7.21/kotlin-annotation-processing-gradle-1.7.21.jar" + ], + "hash": "sha256-RhyKdFvNVeRyXykBIVnUdOEor/G4KlPR80UkYFK5cwk=" + }, + "kotlin-annotation-processing-gradle-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.7.21/kotlin-annotation-processing-gradle-1.7.21.pom" + ], + "hash": "sha256-r2JZxfjfTezw8FXmZcTLaP8TtK9c1HfuHTO/7gAaFr4=" + } + }, + "org.jetbrains.kotlin:kotlin-android-extensions:1.7.21": { + "kotlin-android-extensions-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-android-extensions/1.7.21/kotlin-android-extensions-1.7.21.jar" + ], + "hash": "sha256-JVeliP7QxmbRVq1uDfXjFOqz1p5m6aJyJ5uaRiQ0xq8=" + }, + "kotlin-android-extensions-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-android-extensions/1.7.21/kotlin-android-extensions-1.7.21.pom" + ], + "hash": "sha256-8pic3UN0A8hyZc/K8GHSFOaGlVyX40ntFWa6FqouDI0=" + } + }, + "org.jetbrains.kotlin:kotlin-compiler-runner:1.7.21": { + "kotlin-compiler-runner-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-runner/1.7.21/kotlin-compiler-runner-1.7.21.jar" + ], + "hash": "sha256-LdVae/7udr97ASbFtx0FuJmBK6a0Cjc1n50T+uIC8yc=" + }, + "kotlin-compiler-runner-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-runner/1.7.21/kotlin-compiler-runner-1.7.21.pom" + ], + "hash": "sha256-+JDieVykDuyu+jpdjkOND3C7YCo5SUe7rOp2Quqy+Tw=" + } + }, + "org.jetbrains.kotlin:kotlin-build-common:1.7.21": { + "kotlin-build-common-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-build-common/1.7.21/kotlin-build-common-1.7.21.jar" + ], + "hash": "sha256-Y3O9HhUPfcsnL1KvvBWZBkCSqddbKM7WvroA/qy6u/8=" + }, + "kotlin-build-common-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-build-common/1.7.21/kotlin-build-common-1.7.21.pom" + ], + "hash": "sha256-msmBVHbIUfFKH3QeG46CJRxyepVGgMdXT4owUn2z718=" + } + }, + "org.jetbrains.kotlin:kotlin-daemon-client:1.7.21": { + "kotlin-daemon-client-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-client/1.7.21/kotlin-daemon-client-1.7.21.jar" + ], + "hash": "sha256-tyPlHq8syE/a+sqHJnk/7I1SFyUNiAv0eDA/JE3UGoU=" + }, + "kotlin-daemon-client-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-client/1.7.21/kotlin-daemon-client-1.7.21.pom" + ], + "hash": "sha256-Be4Gj7v3IvWRSlqiWO6KKLZChF9B1/+bVGhtXKJbvxk=" + } + }, + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.0": { + "kotlinx-coroutines-core-jvm-1.5.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.5.0/kotlinx-coroutines-core-jvm-1.5.0.jar" + ], + "hash": "sha256-eNbMcTX4TWkv83Uvz9H6G74JQNffcGUuTx6u7Ax4r7s=" + }, + "kotlinx-coroutines-core-jvm-1.5.0.module": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.5.0/kotlinx-coroutines-core-jvm-1.5.0.module" + ], + "hash": "sha256-yIXdAoEHbFhDgm3jF+PLzcPYhZ2+71OuHPrNG5xg+W4=" + } + }, + "org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.7.21": { + "kotlin-scripting-compiler-embeddable-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.jar", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.jar" + ], + "hash": "sha256-qu9jHwICEl2ZHZgjRxn4ZK1anW40m/DtRGsTd9gXGKE=" + }, + "kotlin-scripting-compiler-embeddable-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.pom", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.pom" + ], + "hash": "sha256-xHXL2+0BepcMD9y46qu1UNc9E6T+a4e3efxM9S148JM=" + } + }, + "org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.7.21": { + "kotlin-scripting-compiler-impl-embeddable-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.jar", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.jar" + ], + "hash": "sha256-ZOK9uuvzgJSzwh5nCX5Qe4NoTaQTi6h6CwmhMgOXVCg=" + }, + "kotlin-scripting-compiler-impl-embeddable-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.pom", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.pom" + ], + "hash": "sha256-5c0+HEj+qhC1YVqidOFh5/dcFijcJhZ1ALZ0b4gfweM=" + } + }, + "org.jetbrains.kotlin:kotlin-scripting-common:1.7.21": { + "kotlin-scripting-common-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.jar", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.jar" + ], + "hash": "sha256-0ZLMLNlDFecijrkTZqNpdmpoIrPOvKwUwR1MSXM2y6Q=" + }, + "kotlin-scripting-common-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.pom", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.pom" + ], + "hash": "sha256-2xzYRWGPDLQXOK3H72jZ+NIjZ1sFg+NbsMCEA30AWe4=" + } + }, + "org.jetbrains.kotlin:kotlin-scripting-jvm:1.7.21": { + "kotlin-scripting-jvm-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.jar", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.jar" + ], + "hash": "sha256-Uz441a1oFCoFE0HyK8cO113IUGSxk3rPBRN1XMPwSF4=" + }, + "kotlin-scripting-jvm-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.pom", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.pom" + ], + "hash": "sha256-cnwtOnluoiOWPu7P7kHvKygsVbZ+V8O0mgFwpMSbfGE=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.21": { + "kotlin-stdlib-jdk8-1.7.21.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.7.21/kotlin-stdlib-jdk8-1.7.21.jar" + ], + "hash": "sha256-sy5K5+uwVycz/kOThb8DT1+u6LbFhdQW/s+TPpSR044=" + }, + "kotlin-stdlib-jdk8-1.7.21.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.7.21/kotlin-stdlib-jdk8-1.7.21.pom" + ], + "hash": "sha256-bzuTQ8QS1q5ApMePuKcJhklkUKlSjNusdimojhqlg4k=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib:1.7.21": { + "kotlin-stdlib-1.7.21.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.7.21/kotlin-stdlib-1.7.21.jar" + ], + "hash": "sha256-1Gqddz/7ne5P8adIrIRdyOUABcWJMClRdgorUYe93Rk=" + }, + "kotlin-stdlib-1.7.21.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.7.21/kotlin-stdlib-1.7.21.pom" + ], + "hash": "sha256-mzkq1D4vQhJp9jxiBz+ulCN9LjHe7o9msZzBkbTaBqw=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib-common:1.7.21": { + "kotlin-stdlib-common-1.7.21.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.7.21/kotlin-stdlib-common-1.7.21.jar" + ], + "hash": "sha256-5iv+yiNhA6EBciS4oiqEHbXcTbSdgKOb1E27IkaEpmo=" + }, + "kotlin-stdlib-common-1.7.21.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.7.21/kotlin-stdlib-common-1.7.21.pom" + ], + "hash": "sha256-LuberkeOGLGvushzHFvxoUe1dWiT1Z7b+nEWBcNDX4Q=" + } + }, + "org.jetbrains:annotations:13.0": { + "annotations-13.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/annotations/13.0/annotations-13.0.jar" + ], + "hash": "sha256-rOKhDcji1f00kl7KwD5JiLLA+FFlDJS4zvSbob0RFHg=" + }, + "annotations-13.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/annotations/13.0/annotations-13.0.pom" + ], + "hash": "sha256-llrrK+3/NpgZvd4b96CzuJuCR91pyIuGN112Fju4w5c=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.21": { + "kotlin-stdlib-jdk7-1.7.21.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.7.21/kotlin-stdlib-jdk7-1.7.21.jar" + ], + "hash": "sha256-uMqg+XFaIYf0+pmQba5Xy6EM7vmn+Ajb7o6vNjWVWKU=" + }, + "kotlin-stdlib-jdk7-1.7.21.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.7.21/kotlin-stdlib-jdk7-1.7.21.pom" + ], + "hash": "sha256-vy6yU9onofKT0RRpMpRBeF26xRceWB8v7Z1aKm2YaZw=" + } + }, + "org.jetbrains.kotlin:kotlin-script-runtime:1.7.21": { + "kotlin-script-runtime-1.7.21.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-script-runtime/1.7.21/kotlin-script-runtime-1.7.21.jar" + ], + "hash": "sha256-LEmLbZiWTK3dS1hLe0mPmxCPaf8akVOrxlt02uQJJ/Y=" + }, + "kotlin-script-runtime-1.7.21.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-script-runtime/1.7.21/kotlin-script-runtime-1.7.21.pom" + ], + "hash": "sha256-LuSdd/3Dw6l0akiYCbfGQ3fh2NnEXCDZI+MXI5sicwQ=" + } + }, + "org.jetbrains.kotlin:kotlin-reflect:1.7.21": { + "kotlin-reflect-1.7.21.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.7.21/kotlin-reflect-1.7.21.jar" + ], + "hash": "sha256-wbF65MSTF+7Sb3ecM8lpBEbFZp6zx+Jsibbg1s8sogQ=" + }, + "kotlin-reflect-1.7.21.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.7.21/kotlin-reflect-1.7.21.pom" + ], + "hash": "sha256-Xn69/iAG9vHksPORwbqBhTmKj2NF2xpStYTx40Cz8EM=" + } + }, + "org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:1.7.21": { + "kotlin-klib-commonizer-embeddable-1.7.21.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-klib-commonizer-embeddable/1.7.21/kotlin-klib-commonizer-embeddable-1.7.21.jar" + ], + "hash": "sha256-nTpktCC+2+20HV5tsJ28h2FKffCBR5PACQqDYJBp+1Y=" + }, + "kotlin-klib-commonizer-embeddable-1.7.21.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-klib-commonizer-embeddable/1.7.21/kotlin-klib-commonizer-embeddable-1.7.21.pom" + ], + "hash": "sha256-bOmRoyzYOdq3wbf88+1xbr6XgbRgg3ViDC9fH8RwjrA=" + } + } +} \ No newline at end of file diff --git a/fixtures/golden/plugin/resolves-from-default-repo.kotlin.json b/fixtures/golden/plugin/resolves-from-default-repo.kotlin.json new file mode 100644 index 0000000..58789dd --- /dev/null +++ b/fixtures/golden/plugin/resolves-from-default-repo.kotlin.json @@ -0,0 +1,494 @@ +{ + "org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.7.21": { + "org.jetbrains.kotlin.jvm.gradle.plugin-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.7.21/org.jetbrains.kotlin.jvm.gradle.plugin-1.7.21.pom" + ], + "hash": "sha256-18S+c5nTziimR77ivh3nCwUdpLqoz9X4KYNDJ2UKD30=" + } + }, + "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.21": { + "kotlin-gradle-plugin-1.7.21-gradle71.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin/1.7.21/kotlin-gradle-plugin-1.7.21-gradle71.jar" + ], + "hash": "sha256-P12cqfSxiGOZjcVpNIk9m1ICRRzucJ+uuXbI+rI2cyI=" + }, + "kotlin-gradle-plugin-1.7.21.module": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin/1.7.21/kotlin-gradle-plugin-1.7.21.module" + ], + "hash": "sha256-j6I2KYtJBynes0XjG8ZPKSj3wbXxwjH8ZtvINlnBZ+E=" + } + }, + "org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.7.21": { + "kotlin-gradle-plugin-api-1.7.21-gradle71.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.7.21/kotlin-gradle-plugin-api-1.7.21-gradle71.jar" + ], + "hash": "sha256-rflytT2LY7s2jZA88y6bB+pTZW6PnaXxDfuv03gxviE=" + }, + "kotlin-gradle-plugin-api-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.7.21/kotlin-gradle-plugin-api-1.7.21.jar" + ], + "hash": "sha256-rflytT2LY7s2jZA88y6bB+pTZW6PnaXxDfuv03gxviE=" + }, + "kotlin-gradle-plugin-api-1.7.21.module": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.7.21/kotlin-gradle-plugin-api-1.7.21.module" + ], + "hash": "sha256-zGXnGhweng0JaG9cpJGORShIY1q7VCl15HwYlnw6A10=" + } + }, + "org.jetbrains.kotlin:kotlin-native-utils:1.7.21": { + "kotlin-native-utils-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-native-utils/1.7.21/kotlin-native-utils-1.7.21.jar" + ], + "hash": "sha256-k1KYF/2Nj9hlItZqqtyr0UKhcueMz+uUnNKJ40xw+Qs=" + }, + "kotlin-native-utils-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-native-utils/1.7.21/kotlin-native-utils-1.7.21.pom" + ], + "hash": "sha256-CEYFdUhagoAZC0g8H3fyCk063IegIXTzDuxVdNm65FY=" + } + }, + "org.jetbrains.kotlin:kotlin-util-io:1.7.21": { + "kotlin-util-io-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-io/1.7.21/kotlin-util-io-1.7.21.jar" + ], + "hash": "sha256-7MKI4AQqAUdgOeILbOXgaRj+8fic+J9V39KO8Xwm800=" + }, + "kotlin-util-io-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-io/1.7.21/kotlin-util-io-1.7.21.pom" + ], + "hash": "sha256-ziTM1kPWW+8Cey9uINCnkhdq29ug2eVVmS5CR6Y3Ne8=" + } + }, + "org.jetbrains.kotlin:kotlin-project-model:1.7.21": { + "kotlin-project-model-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-project-model/1.7.21/kotlin-project-model-1.7.21.jar" + ], + "hash": "sha256-4htTvrj3SxM6Y4mClPSlfcSiKJvoVfZrD5rosVYjFT8=" + }, + "kotlin-project-model-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-project-model/1.7.21/kotlin-project-model-1.7.21.pom" + ], + "hash": "sha256-JQfT7SKoHyssNSxMUOY1MivHEQClFQJN0NtQRifJ8Bs=" + } + }, + "org.jetbrains.kotlin:kotlin-tooling-core:1.7.21": { + "kotlin-tooling-core-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-tooling-core/1.7.21/kotlin-tooling-core-1.7.21.jar" + ], + "hash": "sha256-N5fxg1NC+8EuycHU+YMyugKCkaMyUakHySJ9j9lK7kg=" + }, + "kotlin-tooling-core-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-tooling-core/1.7.21/kotlin-tooling-core-1.7.21.pom" + ], + "hash": "sha256-tw2g1Eorhw7Lz85ZcMMOOOLs3htfQqHdRC0TA5gSKUY=" + } + }, + "org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.7.21": { + "kotlin-gradle-plugin-model-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.7.21/kotlin-gradle-plugin-model-1.7.21.jar" + ], + "hash": "sha256-FNP/F7o8tMi+uK3297QFB4gTS4kbsTyr5yPIwQ0dDhg=" + }, + "kotlin-gradle-plugin-model-1.7.21.module": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.7.21/kotlin-gradle-plugin-model-1.7.21.module" + ], + "hash": "sha256-kCJoZCp1guVF4xgQnjdIw3WxOLCKFVuBX2yAi7vuR7U=" + } + }, + "org.jetbrains.kotlin:kotlin-gradle-plugin-idea:1.7.21": { + "kotlin-gradle-plugin-idea-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.7.21/kotlin-gradle-plugin-idea-1.7.21.jar" + ], + "hash": "sha256-C1dqyzeBqctWEKphxbev3zKQ/C2digzUv+FTe4dcReY=" + }, + "kotlin-gradle-plugin-idea-1.7.21.module": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.7.21/kotlin-gradle-plugin-idea-1.7.21.module" + ], + "hash": "sha256-ygHy2JJMcpaXMax+oVbwi7GP60LDEAClIj2dwW1ZuTg=" + } + }, + "org.jetbrains.kotlin:kotlin-gradle-plugin-idea-proto:1.7.21": { + "kotlin-gradle-plugin-idea-proto-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea-proto/1.7.21/kotlin-gradle-plugin-idea-proto-1.7.21.jar" + ], + "hash": "sha256-NZhwZybLzo0oE05oiZw9WAv3LH6/kJcUHY28rtgnmHg=" + }, + "kotlin-gradle-plugin-idea-proto-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea-proto/1.7.21/kotlin-gradle-plugin-idea-proto-1.7.21.pom" + ], + "hash": "sha256-PRwDYK9odF8qAyoMAYR//Pnriq1wa/ZZydhAoYTsXyM=" + } + }, + "org.jetbrains.kotlin:kotlin-util-klib:1.7.21": { + "kotlin-util-klib-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-klib/1.7.21/kotlin-util-klib-1.7.21.jar" + ], + "hash": "sha256-UgkkU0RkIN+7h4BN6s6yGfVI53fm3xK35wRKOmaHEgs=" + }, + "kotlin-util-klib-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-klib/1.7.21/kotlin-util-klib-1.7.21.pom" + ], + "hash": "sha256-D8d7J3Rc+kzuX+AA5tEpmtSUT3rMB4A7u8ws0rAT3oU=" + } + }, + "org.jetbrains.kotlin:kotlin-klib-commonizer-api:1.7.21": { + "kotlin-klib-commonizer-api-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.7.21/kotlin-klib-commonizer-api-1.7.21.jar" + ], + "hash": "sha256-MOGWrbAAH9F7ZgNe2QcNPw5Hui0ycTt1wwPGt7e3FeI=" + }, + "kotlin-klib-commonizer-api-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.7.21/kotlin-klib-commonizer-api-1.7.21.pom" + ], + "hash": "sha256-so6g3vy5lNH7U6e7olh9J0DG0mAXk2UglP1ox0Ul0CA=" + } + }, + "org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.21": { + "kotlin-compiler-embeddable-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.jar", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.jar" + ], + "hash": "sha256-Ty5JK8x5XgaA4/h67qGtrp8wbK9SBAuUpvoPiP2skvk=" + }, + "kotlin-compiler-embeddable-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.pom", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.pom" + ], + "hash": "sha256-CwIzMip2MO/eEzUmjkYSPw1tNjg5gg/TfE7Lbv+njjs=" + } + }, + "org.jetbrains.kotlin:kotlin-daemon-embeddable:1.7.21": { + "kotlin-daemon-embeddable-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.jar", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.jar" + ], + "hash": "sha256-A+bwJUNSJIlOSe5e2EfLCwtKh540z6uQ1wzakmKnV00=" + }, + "kotlin-daemon-embeddable-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.pom", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.pom" + ], + "hash": "sha256-vB3pwgh7ouTlQQF6i66PQF7IAKGK5MJH6R8rVedh5kk=" + } + }, + "org.jetbrains.intellij.deps:trove4j:1.0.20200330": { + "trove4j-1.0.20200330.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.jar", + "https://repo.maven.apache.org/maven2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.jar" + ], + "hash": "sha256-xf1yW/+rUYRr88d9sTg8YKquv+G3/i8A0j/ht98KQ50=" + }, + "trove4j-1.0.20200330.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.pom", + "https://repo.maven.apache.org/maven2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.pom" + ], + "hash": "sha256-h3IcuqZaPJfYsbqdIHhA8WTJ/jh1n8nqEP/iZWX40+k=" + } + }, + "net.java.dev.jna:jna:5.6.0": { + "jna-5.6.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.jar", + "https://repo.maven.apache.org/maven2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.jar" + ], + "hash": "sha256-VVfiNaiqL5dm1dxgnWeUjyqIMsLXls6p7x1svgs7fq8=" + }, + "jna-5.6.0.pom": { + "urls": [ + "https://plugins.gradle.org/m2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.pom", + "https://repo.maven.apache.org/maven2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.pom" + ], + "hash": "sha256-X+gbAlWXjyRhbTexBgi3lJil8wc+HZsgONhzaoMfJgg=" + } + }, + "org.jetbrains.kotlin:kotlin-annotation-processing-gradle:1.7.21": { + "kotlin-annotation-processing-gradle-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.7.21/kotlin-annotation-processing-gradle-1.7.21.jar" + ], + "hash": "sha256-RhyKdFvNVeRyXykBIVnUdOEor/G4KlPR80UkYFK5cwk=" + }, + "kotlin-annotation-processing-gradle-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.7.21/kotlin-annotation-processing-gradle-1.7.21.pom" + ], + "hash": "sha256-r2JZxfjfTezw8FXmZcTLaP8TtK9c1HfuHTO/7gAaFr4=" + } + }, + "org.jetbrains.kotlin:kotlin-android-extensions:1.7.21": { + "kotlin-android-extensions-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-android-extensions/1.7.21/kotlin-android-extensions-1.7.21.jar" + ], + "hash": "sha256-JVeliP7QxmbRVq1uDfXjFOqz1p5m6aJyJ5uaRiQ0xq8=" + }, + "kotlin-android-extensions-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-android-extensions/1.7.21/kotlin-android-extensions-1.7.21.pom" + ], + "hash": "sha256-8pic3UN0A8hyZc/K8GHSFOaGlVyX40ntFWa6FqouDI0=" + } + }, + "org.jetbrains.kotlin:kotlin-compiler-runner:1.7.21": { + "kotlin-compiler-runner-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-runner/1.7.21/kotlin-compiler-runner-1.7.21.jar" + ], + "hash": "sha256-LdVae/7udr97ASbFtx0FuJmBK6a0Cjc1n50T+uIC8yc=" + }, + "kotlin-compiler-runner-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-runner/1.7.21/kotlin-compiler-runner-1.7.21.pom" + ], + "hash": "sha256-+JDieVykDuyu+jpdjkOND3C7YCo5SUe7rOp2Quqy+Tw=" + } + }, + "org.jetbrains.kotlin:kotlin-build-common:1.7.21": { + "kotlin-build-common-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-build-common/1.7.21/kotlin-build-common-1.7.21.jar" + ], + "hash": "sha256-Y3O9HhUPfcsnL1KvvBWZBkCSqddbKM7WvroA/qy6u/8=" + }, + "kotlin-build-common-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-build-common/1.7.21/kotlin-build-common-1.7.21.pom" + ], + "hash": "sha256-msmBVHbIUfFKH3QeG46CJRxyepVGgMdXT4owUn2z718=" + } + }, + "org.jetbrains.kotlin:kotlin-daemon-client:1.7.21": { + "kotlin-daemon-client-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-client/1.7.21/kotlin-daemon-client-1.7.21.jar" + ], + "hash": "sha256-tyPlHq8syE/a+sqHJnk/7I1SFyUNiAv0eDA/JE3UGoU=" + }, + "kotlin-daemon-client-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-client/1.7.21/kotlin-daemon-client-1.7.21.pom" + ], + "hash": "sha256-Be4Gj7v3IvWRSlqiWO6KKLZChF9B1/+bVGhtXKJbvxk=" + } + }, + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.0": { + "kotlinx-coroutines-core-jvm-1.5.0.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.5.0/kotlinx-coroutines-core-jvm-1.5.0.jar" + ], + "hash": "sha256-eNbMcTX4TWkv83Uvz9H6G74JQNffcGUuTx6u7Ax4r7s=" + }, + "kotlinx-coroutines-core-jvm-1.5.0.module": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.5.0/kotlinx-coroutines-core-jvm-1.5.0.module" + ], + "hash": "sha256-yIXdAoEHbFhDgm3jF+PLzcPYhZ2+71OuHPrNG5xg+W4=" + } + }, + "org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.7.21": { + "kotlin-scripting-compiler-embeddable-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.jar", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.jar" + ], + "hash": "sha256-qu9jHwICEl2ZHZgjRxn4ZK1anW40m/DtRGsTd9gXGKE=" + }, + "kotlin-scripting-compiler-embeddable-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.pom", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.pom" + ], + "hash": "sha256-xHXL2+0BepcMD9y46qu1UNc9E6T+a4e3efxM9S148JM=" + } + }, + "org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.7.21": { + "kotlin-scripting-compiler-impl-embeddable-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.jar", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.jar" + ], + "hash": "sha256-ZOK9uuvzgJSzwh5nCX5Qe4NoTaQTi6h6CwmhMgOXVCg=" + }, + "kotlin-scripting-compiler-impl-embeddable-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.pom", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.pom" + ], + "hash": "sha256-5c0+HEj+qhC1YVqidOFh5/dcFijcJhZ1ALZ0b4gfweM=" + } + }, + "org.jetbrains.kotlin:kotlin-scripting-common:1.7.21": { + "kotlin-scripting-common-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.jar", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.jar" + ], + "hash": "sha256-0ZLMLNlDFecijrkTZqNpdmpoIrPOvKwUwR1MSXM2y6Q=" + }, + "kotlin-scripting-common-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.pom", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.pom" + ], + "hash": "sha256-2xzYRWGPDLQXOK3H72jZ+NIjZ1sFg+NbsMCEA30AWe4=" + } + }, + "org.jetbrains.kotlin:kotlin-scripting-jvm:1.7.21": { + "kotlin-scripting-jvm-1.7.21.jar": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.jar", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.jar" + ], + "hash": "sha256-Uz441a1oFCoFE0HyK8cO113IUGSxk3rPBRN1XMPwSF4=" + }, + "kotlin-scripting-jvm-1.7.21.pom": { + "urls": [ + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.pom", + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.pom" + ], + "hash": "sha256-cnwtOnluoiOWPu7P7kHvKygsVbZ+V8O0mgFwpMSbfGE=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.21": { + "kotlin-stdlib-jdk8-1.7.21.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.7.21/kotlin-stdlib-jdk8-1.7.21.jar" + ], + "hash": "sha256-sy5K5+uwVycz/kOThb8DT1+u6LbFhdQW/s+TPpSR044=" + }, + "kotlin-stdlib-jdk8-1.7.21.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.7.21/kotlin-stdlib-jdk8-1.7.21.pom" + ], + "hash": "sha256-bzuTQ8QS1q5ApMePuKcJhklkUKlSjNusdimojhqlg4k=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib:1.7.21": { + "kotlin-stdlib-1.7.21.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.7.21/kotlin-stdlib-1.7.21.jar" + ], + "hash": "sha256-1Gqddz/7ne5P8adIrIRdyOUABcWJMClRdgorUYe93Rk=" + }, + "kotlin-stdlib-1.7.21.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.7.21/kotlin-stdlib-1.7.21.pom" + ], + "hash": "sha256-mzkq1D4vQhJp9jxiBz+ulCN9LjHe7o9msZzBkbTaBqw=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib-common:1.7.21": { + "kotlin-stdlib-common-1.7.21.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.7.21/kotlin-stdlib-common-1.7.21.jar" + ], + "hash": "sha256-5iv+yiNhA6EBciS4oiqEHbXcTbSdgKOb1E27IkaEpmo=" + }, + "kotlin-stdlib-common-1.7.21.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.7.21/kotlin-stdlib-common-1.7.21.pom" + ], + "hash": "sha256-LuberkeOGLGvushzHFvxoUe1dWiT1Z7b+nEWBcNDX4Q=" + } + }, + "org.jetbrains:annotations:13.0": { + "annotations-13.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/annotations/13.0/annotations-13.0.jar" + ], + "hash": "sha256-rOKhDcji1f00kl7KwD5JiLLA+FFlDJS4zvSbob0RFHg=" + }, + "annotations-13.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/annotations/13.0/annotations-13.0.pom" + ], + "hash": "sha256-llrrK+3/NpgZvd4b96CzuJuCR91pyIuGN112Fju4w5c=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.21": { + "kotlin-stdlib-jdk7-1.7.21.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.7.21/kotlin-stdlib-jdk7-1.7.21.jar" + ], + "hash": "sha256-uMqg+XFaIYf0+pmQba5Xy6EM7vmn+Ajb7o6vNjWVWKU=" + }, + "kotlin-stdlib-jdk7-1.7.21.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.7.21/kotlin-stdlib-jdk7-1.7.21.pom" + ], + "hash": "sha256-vy6yU9onofKT0RRpMpRBeF26xRceWB8v7Z1aKm2YaZw=" + } + }, + "org.jetbrains.kotlin:kotlin-script-runtime:1.7.21": { + "kotlin-script-runtime-1.7.21.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-script-runtime/1.7.21/kotlin-script-runtime-1.7.21.jar" + ], + "hash": "sha256-LEmLbZiWTK3dS1hLe0mPmxCPaf8akVOrxlt02uQJJ/Y=" + }, + "kotlin-script-runtime-1.7.21.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-script-runtime/1.7.21/kotlin-script-runtime-1.7.21.pom" + ], + "hash": "sha256-LuSdd/3Dw6l0akiYCbfGQ3fh2NnEXCDZI+MXI5sicwQ=" + } + }, + "org.jetbrains.kotlin:kotlin-reflect:1.7.21": { + "kotlin-reflect-1.7.21.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.7.21/kotlin-reflect-1.7.21.jar" + ], + "hash": "sha256-wbF65MSTF+7Sb3ecM8lpBEbFZp6zx+Jsibbg1s8sogQ=" + }, + "kotlin-reflect-1.7.21.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.7.21/kotlin-reflect-1.7.21.pom" + ], + "hash": "sha256-Xn69/iAG9vHksPORwbqBhTmKj2NF2xpStYTx40Cz8EM=" + } + }, + "org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:1.7.21": { + "kotlin-klib-commonizer-embeddable-1.7.21.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-klib-commonizer-embeddable/1.7.21/kotlin-klib-commonizer-embeddable-1.7.21.jar" + ], + "hash": "sha256-nTpktCC+2+20HV5tsJ28h2FKffCBR5PACQqDYJBp+1Y=" + }, + "kotlin-klib-commonizer-embeddable-1.7.21.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-klib-commonizer-embeddable/1.7.21/kotlin-klib-commonizer-embeddable-1.7.21.pom" + ], + "hash": "sha256-bOmRoyzYOdq3wbf88+1xbr6XgbRgg3ViDC9fH8RwjrA=" + } + } +} \ No newline at end of file diff --git a/fixtures/golden/s3/maven-snapshot.groovy.json b/fixtures/golden/s3/maven-snapshot.groovy.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/fixtures/golden/s3/maven-snapshot.groovy.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/fixtures/golden/s3/maven-snapshot.kotlin.json b/fixtures/golden/s3/maven-snapshot.kotlin.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/fixtures/golden/s3/maven-snapshot.kotlin.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/fixtures/golden/s3/maven.groovy.json b/fixtures/golden/s3/maven.groovy.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/fixtures/golden/s3/maven.groovy.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/fixtures/golden/s3/maven.kotlin.json b/fixtures/golden/s3/maven.kotlin.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/fixtures/golden/s3/maven.kotlin.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/fixtures/golden/settings/buildscript.groovy.json b/fixtures/golden/settings/buildscript.groovy.json new file mode 100644 index 0000000..09eb001 --- /dev/null +++ b/fixtures/golden/settings/buildscript.groovy.json @@ -0,0 +1,16 @@ +{ + "org.apache:test:1.0.0": { + "test-1.0.0.jar": { + "urls": [ + "file:/home/tad/proj/gradle2nix/fixtures/repositories/m2/org/apache/test/1.0.0/test-1.0.0.jar" + ], + "hash": "sha256-M95zEuAwVCam7c2rKIET5qs4Q60sA84RyTA3a9jdQd8=" + }, + "test-1.0.0.pom": { + "urls": [ + "file:/home/tad/proj/gradle2nix/fixtures/repositories/m2/org/apache/test/1.0.0/test-1.0.0.pom" + ], + "hash": "sha256-sYk8m4+T+hRJ+43tpPkthrE/JftrsMnmuzORCLCK1To=" + } + } +} \ No newline at end of file diff --git a/fixtures/golden/settings/dependency-resolution-management.kotlin.json b/fixtures/golden/settings/dependency-resolution-management.kotlin.json new file mode 100644 index 0000000..09eb001 --- /dev/null +++ b/fixtures/golden/settings/dependency-resolution-management.kotlin.json @@ -0,0 +1,16 @@ +{ + "org.apache:test:1.0.0": { + "test-1.0.0.jar": { + "urls": [ + "file:/home/tad/proj/gradle2nix/fixtures/repositories/m2/org/apache/test/1.0.0/test-1.0.0.jar" + ], + "hash": "sha256-M95zEuAwVCam7c2rKIET5qs4Q60sA84RyTA3a9jdQd8=" + }, + "test-1.0.0.pom": { + "urls": [ + "file:/home/tad/proj/gradle2nix/fixtures/repositories/m2/org/apache/test/1.0.0/test-1.0.0.pom" + ], + "hash": "sha256-sYk8m4+T+hRJ+43tpPkthrE/JftrsMnmuzORCLCK1To=" + } + } +} \ No newline at end of file diff --git a/fixtures/golden/subprojects/multi-module.groovy.json b/fixtures/golden/subprojects/multi-module.groovy.json new file mode 100644 index 0000000..1503a9e --- /dev/null +++ b/fixtures/golden/subprojects/multi-module.groovy.json @@ -0,0 +1,114 @@ +{ + "junit:junit:4.12": { + "junit-4.12.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/junit/junit/4.12/junit-4.12.jar" + ], + "hash": "sha256-WXIfCAXiI9hLkGd4h9n/Vn3FNNfFAsqQPAwrF/BcEWo=" + }, + "junit-4.12.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/junit/junit/4.12/junit-4.12.pom" + ], + "hash": "sha256-kPFj944/+28cetl96efrpO6iWAcUG4XW0SvmfKJUScQ=" + } + }, + "org.hamcrest:hamcrest-core:1.3": { + "hamcrest-core-1.3.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar" + ], + "hash": "sha256-Zv3vkelzk0jfeglqo4SlaF9Oh1WEzOiThqekclHE2Ok=" + }, + "hamcrest-core-1.3.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.pom" + ], + "hash": "sha256-/eOGp5BRc6GxA95quCBydYS1DQ4yKC4nl3h8IKZP+pM=" + } + }, + "com.squareup.okio:okio:2.2.2": { + "okio-2.2.2.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/2.2.2/okio-2.2.2.jar" + ], + "hash": "sha256-5YyXQGprsROIk3UCmaxjxqoEs4trSerhv8rRpj75uhs=" + }, + "okio-2.2.2.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/2.2.2/okio-2.2.2.pom" + ], + "hash": "sha256-/WIZiPf2lXAlc13G3QkLAKIPOju413ynkDYHf2KbFAs=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib:1.2.60": { + "kotlin-stdlib-1.2.60.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.2.60/kotlin-stdlib-1.2.60.jar" + ], + "hash": "sha256-ahMCmPUXGsUqHiSW9+rnhbb1ZBbqPMuZ5DRNBNg/8HE=" + }, + "kotlin-stdlib-1.2.60.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.2.60/kotlin-stdlib-1.2.60.pom" + ], + "hash": "sha256-5jKJkgnmtMqrlA/YLk7GOjLjJkP4Fff6cJdkeJDXnxg=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib-common:1.2.60": { + "kotlin-stdlib-common-1.2.60.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.2.60/kotlin-stdlib-common-1.2.60.jar" + ], + "hash": "sha256-CbQ3WgZc8SeryZjF3PIrFmTEWvQrSJSZ16j0+Kt5P7E=" + }, + "kotlin-stdlib-common-1.2.60.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.2.60/kotlin-stdlib-common-1.2.60.pom" + ], + "hash": "sha256-gwwnrx4c8k8PUm6kV5AcQ/OMGbtvfl03Y8PSU98bjaE=" + } + }, + "org.jetbrains:annotations:13.0": { + "annotations-13.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/annotations/13.0/annotations-13.0.jar" + ], + "hash": "sha256-rOKhDcji1f00kl7KwD5JiLLA+FFlDJS4zvSbob0RFHg=" + }, + "annotations-13.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/annotations/13.0/annotations-13.0.pom" + ], + "hash": "sha256-llrrK+3/NpgZvd4b96CzuJuCR91pyIuGN112Fju4w5c=" + } + }, + "com.squareup.moshi:moshi:1.8.0": { + "moshi-1.8.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/moshi/moshi/1.8.0/moshi-1.8.0.jar" + ], + "hash": "sha256-Qv50bSaU6hH+agK+zZ2iyj2v6Xye/VCg+a9cRZbnSmo=" + }, + "moshi-1.8.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/moshi/moshi/1.8.0/moshi-1.8.0.pom" + ], + "hash": "sha256-FLuAWbnddiACWSkN+IfjfmaaB0qsnImUAePIEC/lII8=" + } + }, + "com.squareup.okio:okio:1.16.0": { + "okio-1.16.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/1.16.0/okio-1.16.0.jar" + ], + "hash": "sha256-7ASE/xkDZA44RcKxCruZ7/LTIwj/40WeX5IwmkUbnH4=" + }, + "okio-1.16.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/1.16.0/okio-1.16.0.pom" + ], + "hash": "sha256-HSUhYhwIdRI6qRMRsv6O3v0O2T9mvm3+oYzGG8XJnjY=" + } + } +} \ No newline at end of file diff --git a/fixtures/golden/subprojects/multi-module.kotlin.json b/fixtures/golden/subprojects/multi-module.kotlin.json new file mode 100644 index 0000000..1503a9e --- /dev/null +++ b/fixtures/golden/subprojects/multi-module.kotlin.json @@ -0,0 +1,114 @@ +{ + "junit:junit:4.12": { + "junit-4.12.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/junit/junit/4.12/junit-4.12.jar" + ], + "hash": "sha256-WXIfCAXiI9hLkGd4h9n/Vn3FNNfFAsqQPAwrF/BcEWo=" + }, + "junit-4.12.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/junit/junit/4.12/junit-4.12.pom" + ], + "hash": "sha256-kPFj944/+28cetl96efrpO6iWAcUG4XW0SvmfKJUScQ=" + } + }, + "org.hamcrest:hamcrest-core:1.3": { + "hamcrest-core-1.3.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar" + ], + "hash": "sha256-Zv3vkelzk0jfeglqo4SlaF9Oh1WEzOiThqekclHE2Ok=" + }, + "hamcrest-core-1.3.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.pom" + ], + "hash": "sha256-/eOGp5BRc6GxA95quCBydYS1DQ4yKC4nl3h8IKZP+pM=" + } + }, + "com.squareup.okio:okio:2.2.2": { + "okio-2.2.2.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/2.2.2/okio-2.2.2.jar" + ], + "hash": "sha256-5YyXQGprsROIk3UCmaxjxqoEs4trSerhv8rRpj75uhs=" + }, + "okio-2.2.2.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/2.2.2/okio-2.2.2.pom" + ], + "hash": "sha256-/WIZiPf2lXAlc13G3QkLAKIPOju413ynkDYHf2KbFAs=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib:1.2.60": { + "kotlin-stdlib-1.2.60.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.2.60/kotlin-stdlib-1.2.60.jar" + ], + "hash": "sha256-ahMCmPUXGsUqHiSW9+rnhbb1ZBbqPMuZ5DRNBNg/8HE=" + }, + "kotlin-stdlib-1.2.60.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.2.60/kotlin-stdlib-1.2.60.pom" + ], + "hash": "sha256-5jKJkgnmtMqrlA/YLk7GOjLjJkP4Fff6cJdkeJDXnxg=" + } + }, + "org.jetbrains.kotlin:kotlin-stdlib-common:1.2.60": { + "kotlin-stdlib-common-1.2.60.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.2.60/kotlin-stdlib-common-1.2.60.jar" + ], + "hash": "sha256-CbQ3WgZc8SeryZjF3PIrFmTEWvQrSJSZ16j0+Kt5P7E=" + }, + "kotlin-stdlib-common-1.2.60.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.2.60/kotlin-stdlib-common-1.2.60.pom" + ], + "hash": "sha256-gwwnrx4c8k8PUm6kV5AcQ/OMGbtvfl03Y8PSU98bjaE=" + } + }, + "org.jetbrains:annotations:13.0": { + "annotations-13.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/annotations/13.0/annotations-13.0.jar" + ], + "hash": "sha256-rOKhDcji1f00kl7KwD5JiLLA+FFlDJS4zvSbob0RFHg=" + }, + "annotations-13.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/org/jetbrains/annotations/13.0/annotations-13.0.pom" + ], + "hash": "sha256-llrrK+3/NpgZvd4b96CzuJuCR91pyIuGN112Fju4w5c=" + } + }, + "com.squareup.moshi:moshi:1.8.0": { + "moshi-1.8.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/moshi/moshi/1.8.0/moshi-1.8.0.jar" + ], + "hash": "sha256-Qv50bSaU6hH+agK+zZ2iyj2v6Xye/VCg+a9cRZbnSmo=" + }, + "moshi-1.8.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/moshi/moshi/1.8.0/moshi-1.8.0.pom" + ], + "hash": "sha256-FLuAWbnddiACWSkN+IfjfmaaB0qsnImUAePIEC/lII8=" + } + }, + "com.squareup.okio:okio:1.16.0": { + "okio-1.16.0.jar": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/1.16.0/okio-1.16.0.jar" + ], + "hash": "sha256-7ASE/xkDZA44RcKxCruZ7/LTIwj/40WeX5IwmkUbnH4=" + }, + "okio-1.16.0.pom": { + "urls": [ + "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/1.16.0/okio-1.16.0.pom" + ], + "hash": "sha256-HSUhYhwIdRI6qRMRsv6O3v0O2T9mvm3+oYzGG8XJnjY=" + } + } +} \ No newline at end of file diff --git a/fixtures/ivy/basic/kotlin/build.gradle.kts b/fixtures/ivy/basic/kotlin/build.gradle.kts index 871283a..e3f4b8a 100644 --- a/fixtures/ivy/basic/kotlin/build.gradle.kts +++ b/fixtures/ivy/basic/kotlin/build.gradle.kts @@ -5,10 +5,10 @@ plugins { repositories { ivy { url = uri("https://asset.opendof.org") - layout("pattern") { - this as IvyPatternRepositoryLayout + patternLayout { ivy("ivy2/[organisation]/[module]/[revision]/ivy(.[platform]).xml") artifact("artifact/[organisation]/[module]/[revision](/[platform])(/[type]s)/[artifact]-[revision](-[classifier]).[ext]") + } } } @@ -17,4 +17,4 @@ dependencies { dependencies { implementation("org.opendof.core-java:dof-cipher-sms4:1.0") } -} \ No newline at end of file +} diff --git a/fixtures/ivy/basic/kotlin/settings.gradle.kts b/fixtures/ivy/basic/kotlin/settings.gradle.kts new file mode 100644 index 0000000..e69de29 diff --git a/fixtures/plugin/resolves-from-default-repo/groovy/build.gradle b/fixtures/plugin/resolves-from-default-repo/groovy/build.gradle index 029a04c..45976dc 100644 --- a/fixtures/plugin/resolves-from-default-repo/groovy/build.gradle +++ b/fixtures/plugin/resolves-from-default-repo/groovy/build.gradle @@ -1,7 +1,7 @@ plugins { - id "org.jetbrains.kotlin.jvm" version "1.3.50" + id "org.jetbrains.kotlin.jvm" version "1.7.21" } repositories { - jcenter() + mavenCentral() } diff --git a/fixtures/plugin/resolves-from-default-repo/groovy/settings.gradle b/fixtures/plugin/resolves-from-default-repo/groovy/settings.gradle new file mode 100644 index 0000000..e69de29 diff --git a/fixtures/plugin/resolves-from-default-repo/kotlin/build.gradle.kts b/fixtures/plugin/resolves-from-default-repo/kotlin/build.gradle.kts index b4bfb93..864d671 100644 --- a/fixtures/plugin/resolves-from-default-repo/kotlin/build.gradle.kts +++ b/fixtures/plugin/resolves-from-default-repo/kotlin/build.gradle.kts @@ -1,7 +1,8 @@ + plugins { - kotlin("jvm") version "1.3.50" + kotlin("jvm") version "1.7.21" } repositories { - jcenter() + mavenCentral() } diff --git a/fixtures/plugin/resolves-from-default-repo/kotlin/settings.gradle.kts b/fixtures/plugin/resolves-from-default-repo/kotlin/settings.gradle.kts new file mode 100644 index 0000000..e69de29 diff --git a/fixtures/s3/maven-snapshot/kotlin/build.gradle.kts b/fixtures/s3/maven-snapshot/kotlin/build.gradle.kts index 5eb0cbe..e28300a 100644 --- a/fixtures/s3/maven-snapshot/kotlin/build.gradle.kts +++ b/fixtures/s3/maven-snapshot/kotlin/build.gradle.kts @@ -1,3 +1,4 @@ + plugins { java } @@ -14,4 +15,4 @@ repositories { dependencies { implementation("org.apache:test-SNAPSHOT1:2.0.0-SNAPSHOT") -} \ No newline at end of file +} diff --git a/fixtures/s3/maven/kotlin/build.gradle.kts b/fixtures/s3/maven/kotlin/build.gradle.kts index 9802565..bc21a60 100644 --- a/fixtures/s3/maven/kotlin/build.gradle.kts +++ b/fixtures/s3/maven/kotlin/build.gradle.kts @@ -14,4 +14,4 @@ repositories { dependencies { implementation("org.apache:test:1.0.0") -} \ No newline at end of file +} diff --git a/fixtures/settings/buildscript/groovy/settings.gradle b/fixtures/settings/buildscript/groovy/settings.gradle index 972356a..e4b1866 100644 --- a/fixtures/settings/buildscript/groovy/settings.gradle +++ b/fixtures/settings/buildscript/groovy/settings.gradle @@ -1,7 +1,7 @@ buildscript { repositories { maven { - url 'http://localhost:9999/' + url System.getProperty("org.nixos.gradle2nix.m2") } } dependencies { diff --git a/fixtures/settings/dependency-resolution-management/kotlin/build.gradle.kts b/fixtures/settings/dependency-resolution-management/kotlin/build.gradle.kts index 393d521..8ae3037 100644 --- a/fixtures/settings/dependency-resolution-management/kotlin/build.gradle.kts +++ b/fixtures/settings/dependency-resolution-management/kotlin/build.gradle.kts @@ -1,7 +1,8 @@ + plugins { java } dependencies { implementation("org.apache:test:1.0.0") -} \ No newline at end of file +} diff --git a/fixtures/settings/dependency-resolution-management/kotlin/settings.gradle.kts b/fixtures/settings/dependency-resolution-management/kotlin/settings.gradle.kts index 87bd9db..8292657 100644 --- a/fixtures/settings/dependency-resolution-management/kotlin/settings.gradle.kts +++ b/fixtures/settings/dependency-resolution-management/kotlin/settings.gradle.kts @@ -1,6 +1,6 @@ dependencyResolutionManagement { repositories { - maven { url = uri("http://localhost:9999") } + maven { url = uri(System.getProperty("org.nixos.gradle2nix.m2")) } } repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS) -} \ No newline at end of file +} diff --git a/fixtures/subprojects/dependent-subprojects/groovy/build.gradle b/fixtures/subprojects/dependent-subprojects/groovy/build.gradle deleted file mode 100644 index f924346..0000000 --- a/fixtures/subprojects/dependent-subprojects/groovy/build.gradle +++ /dev/null @@ -1,15 +0,0 @@ -subprojects { - apply plugin: 'java' -} - -project(':child-a') { - dependencies { - implementation project(':child-b') - } -} - -project(':child-b') { - dependencies { - implementation project(':child-c') - } -} \ No newline at end of file diff --git a/fixtures/subprojects/dependent-subprojects/groovy/settings.gradle b/fixtures/subprojects/dependent-subprojects/groovy/settings.gradle deleted file mode 100644 index e7cf411..0000000 --- a/fixtures/subprojects/dependent-subprojects/groovy/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -include ':child-a', ':child-b', ':child-c', ':child-d' \ No newline at end of file diff --git a/fixtures/subprojects/multi-module/groovy/build.gradle b/fixtures/subprojects/multi-module/groovy/build.gradle index 91d2f34..30ab58d 100644 --- a/fixtures/subprojects/multi-module/groovy/build.gradle +++ b/fixtures/subprojects/multi-module/groovy/build.gradle @@ -4,10 +4,10 @@ plugins { allprojects { repositories { - jcenter() + mavenCentral() } } dependencies { testImplementation 'junit:junit:4.12' -} \ No newline at end of file +} diff --git a/fixtures/subprojects/multi-module/kotlin/build.gradle.kts b/fixtures/subprojects/multi-module/kotlin/build.gradle.kts index ba82c83..0611ab5 100644 --- a/fixtures/subprojects/multi-module/kotlin/build.gradle.kts +++ b/fixtures/subprojects/multi-module/kotlin/build.gradle.kts @@ -4,7 +4,7 @@ plugins { allprojects { repositories { - jcenter() + mavenCentral() } } diff --git a/fixtures/subprojects/multi-module/kotlin/child-a/build.gradle.kts b/fixtures/subprojects/multi-module/kotlin/child-a/build.gradle.kts index b98236a..16eb66b 100644 --- a/fixtures/subprojects/multi-module/kotlin/child-a/build.gradle.kts +++ b/fixtures/subprojects/multi-module/kotlin/child-a/build.gradle.kts @@ -1,3 +1,4 @@ + plugins { java } diff --git a/fixtures/subprojects/multi-module/kotlin/child-b/build.gradle.kts b/fixtures/subprojects/multi-module/kotlin/child-b/build.gradle.kts index 7b27bde..5468047 100644 --- a/fixtures/subprojects/multi-module/kotlin/child-b/build.gradle.kts +++ b/fixtures/subprojects/multi-module/kotlin/child-b/build.gradle.kts @@ -1,3 +1,4 @@ + plugins { java } diff --git a/gradle.properties b/gradle.properties index 527730c..db26ac0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,5 @@ org.gradle.jvmargs='-Dfile.encoding=UTF-8' +org.gradle.caching=true +org.gradle.configuration-cache=true VERSION=1.0.0-rc2 - -shadowVersion=6.1.0 -stutterVersion=0.6.0 \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..ffd526f --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,43 @@ +[versions] +gradle = "8.3" +kotlin = "1.9.0" # Current embedded Gradle kotlin version +ksp = "1.9.0-1.0.13" + +[libraries] +clikt = "com.github.ajalt:clikt:+" +gradle-dependencyGraph = "org.gradle:github-dependency-graph-gradle-plugin:+" +gradle-toolingApi = { module = "org.gradle:gradle-tooling-api", version.ref = "gradle" } +ivy = "org.apache.ivy:ivy:+" +javalin = "io.javalin:javalin:+" +junit-jupiter-api = "org.junit.jupiter:junit-jupiter-api:+" +junit-jupiter-engine = "org.junit.jupiter:junit-jupiter-engine:+" +junit-jupiter-params = "org.junit.jupiter:junit-jupiter-params:+" +junit-platformLauncher = "org.junit.platform:junit-platform-launcher:+" +kotest-runner = "io.kotest:kotest-runner-junit5:+" +kotest-assertions = "io.kotest:kotest-assertions-core:+" +maven-repositoryMetadata = "org.apache.maven:maven-repository-metadata:+" +minutest = "dev.minutest:minutest:+" +moshi = "com.squareup.moshi:moshi:+" +moshi-adapters = "com.squareup.moshi:moshi-adapters:+" +moshi-kotlin = "com.squareup.moshi:moshi-kotlin:+" +moshi-kotlinCodegen = "com.squareup.moshi:moshi-kotlin-codegen:+" +okio = "com.squareup.okio:okio:+" +s3 = "com.amazonaws:aws-java-sdk-s3:+" +s3mock = "com.adobe.testing:s3mock-junit5:+" +semver = "net.swiftzer.semver:semver:+" +serialization-json = "org.jetbrains.kotlinx:kotlinx-serialization-json:+" +slf4j-api = "org.slf4j:slf4j-api:+" +slf4j-simple = "org.slf4j:slf4j-simple:+" +spek-dsl = "org.spekframework.spek2:spek-dsl-jvm:+" +spek-runner = "org.spekframework.spek2:spek-runner-junit5:+" +strikt = "io.strikt:strikt-core:+" + +[plugins] +pluginPublish = { id = "com.gradle.plugin-publish", version = "1.2.1" } +kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } +kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } +ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } +shadow = { id = "com.github.johnrengelman.shadow", version = "8.1.1" } +stutter = { id = "org.ajoberstar.stutter", version = "0.7.2" } + +[bundles] diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e708b1c..943f0cb 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1c4bcc2..03bc515 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip +networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 4f906e0..65dcd68 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,101 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -106,80 +140,105 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin or MSYS, switch paths to Windows format before running java -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 - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=`expr $i + 1` - done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index ac1b06f..6689b85 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/ivy/build.gradle.kts b/ivy/build.gradle.kts deleted file mode 100644 index 1cc1168..0000000 --- a/ivy/build.gradle.kts +++ /dev/null @@ -1,24 +0,0 @@ -plugins { - kotlin("jvm") -} - -dependencies { - api("org.apache.ivy:ivy:latest.release") - api("com.amazonaws:aws-java-sdk-s3:latest.release") - - testImplementation("com.adobe.testing:s3mock-junit5:latest.release") - testImplementation("io.strikt:strikt-core:latest.release") - testImplementation("org.junit.jupiter:junit-jupiter-api:latest.release") - testImplementation("org.junit.jupiter:junit-jupiter-params:latest.release") - testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:latest.release") - testRuntimeOnly("org.junit.platform:junit-platform-launcher:latest.release") -} - -tasks { - test { - useJUnitPlatform { - includeEngines("junit-jupiter") - } - systemProperty("fixtures", "$rootDir/fixtures") - } -} \ No newline at end of file diff --git a/ivy/gradle.lockfile b/ivy/gradle.lockfile deleted file mode 100644 index 32ae72f..0000000 --- a/ivy/gradle.lockfile +++ /dev/null @@ -1,123 +0,0 @@ -# This is a Gradle generated file for dependency locking. -# Manual edits can break the build and are not advised. -# This file is expected to be part of source control. -ch.qos.logback:logback-classic:1.2.3=testCompileClasspath,testRuntimeClasspath -ch.qos.logback:logback-core:1.2.3=testCompileClasspath,testRuntimeClasspath -com.adobe.testing:s3mock-junit5:2.1.28=testCompileClasspath,testRuntimeClasspath -com.adobe.testing:s3mock-testsupport-common:2.1.28=testCompileClasspath,testRuntimeClasspath -com.adobe.testing:s3mock:2.1.28=testCompileClasspath,testRuntimeClasspath -com.amazonaws:aws-java-sdk-core:1.11.946=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.amazonaws:aws-java-sdk-kms:1.11.946=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.amazonaws:aws-java-sdk-s3:1.11.946=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.amazonaws:jmespath-java:1.11.946=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.christophsturm:filepeek:0.1.2=testRuntimeClasspath -com.fasterxml.jackson.core:jackson-annotations:2.6.0=compileClasspath,runtimeClasspath -com.fasterxml.jackson.core:jackson-annotations:2.9.0=testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-core:2.6.7=compileClasspath,runtimeClasspath -com.fasterxml.jackson.core:jackson-core:2.9.9=testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-databind:2.6.7.4=compileClasspath,runtimeClasspath -com.fasterxml.jackson.core:jackson-databind:2.9.9.3=testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.6.7=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.9=testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.9.9=testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.9=testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.9.9=testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.module:jackson-module-parameter-names:2.9.9=testCompileClasspath,testRuntimeClasspath -com.fasterxml.woodstox:woodstox-core:5.1.0=testCompileClasspath,testRuntimeClasspath -com.fasterxml:classmate:1.3.4=testCompileClasspath,testRuntimeClasspath -com.typesafe.netty:netty-reactive-streams-http:2.0.0=testRuntimeClasspath -com.typesafe.netty:netty-reactive-streams:2.0.0=testRuntimeClasspath -commons-codec:commons-codec:1.11=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -commons-io:commons-io:2.6=testCompileClasspath,testRuntimeClasspath -commons-logging:commons-logging:1.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-buffer:4.1.33.Final=testRuntimeClasspath -io.netty:netty-codec-http2:4.1.33.Final=testRuntimeClasspath -io.netty:netty-codec-http:4.1.33.Final=testRuntimeClasspath -io.netty:netty-codec:4.1.33.Final=testRuntimeClasspath -io.netty:netty-common:4.1.33.Final=testRuntimeClasspath -io.netty:netty-handler:4.1.33.Final=testRuntimeClasspath -io.netty:netty-resolver:4.1.33.Final=testRuntimeClasspath -io.netty:netty-transport-native-epoll:4.1.33.Final=testRuntimeClasspath -io.netty:netty-transport-native-unix-common:4.1.33.Final=testRuntimeClasspath -io.netty:netty-transport:4.1.33.Final=testRuntimeClasspath -io.strikt:strikt-core:0.28.2=testCompileClasspath,testRuntimeClasspath -javax.annotation:javax.annotation-api:1.3.2=testCompileClasspath,testRuntimeClasspath -javax.servlet:javax.servlet-api:3.1.0=testCompileClasspath,testRuntimeClasspath -javax.validation:validation-api:2.0.1.Final=testCompileClasspath,testRuntimeClasspath -joda-time:joda-time:2.8.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.apache.commons:commons-lang3:3.8.1=testCompileClasspath,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.13=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.13=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.apache.ivy:ivy:2.5.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.apache.logging.log4j:log4j-api:2.11.2=testCompileClasspath,testRuntimeClasspath -org.apache.logging.log4j:log4j-to-slf4j:2.11.2=testCompileClasspath,testRuntimeClasspath -org.apiguardian:apiguardian-api:1.1.0=testCompileClasspath,testRuntimeClasspath -org.codehaus.woodstox:stax2-api:4.1=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-continuation:9.4.19.v20190610=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-http:9.4.19.v20190610=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-io:9.4.19.v20190610=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-security:9.4.19.v20190610=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-server:9.4.19.v20190610=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-servlet:9.4.19.v20190610=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-servlets:9.4.19.v20190610=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-util:9.4.19.v20190610=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-webapp:9.4.19.v20190610=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-xml:9.4.19.v20190610=testCompileClasspath,testRuntimeClasspath -org.hibernate.validator:hibernate-validator:6.0.17.Final=testCompileClasspath,testRuntimeClasspath -org.jboss.logging:jboss-logging:3.3.2.Final=testCompileClasspath,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-reflect:1.4.21-2=testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-common:1.4.20=compileClasspath,runtimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-common:1.4.21-2=testCompileClasspath,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.21-2=testCompileClasspath,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.21-2=testCompileClasspath,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib:1.4.20=compileClasspath,runtimeClasspath -org.jetbrains.kotlin:kotlin-stdlib:1.4.21-2=testCompileClasspath,testRuntimeClasspath -org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.4.2=testRuntimeClasspath -org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2=testRuntimeClasspath -org.jetbrains:annotations:13.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.junit.jupiter:junit-jupiter-api:5.7.0=testCompileClasspath,testRuntimeClasspath -org.junit.jupiter:junit-jupiter-engine:5.7.0=testRuntimeClasspath -org.junit.jupiter:junit-jupiter-params:5.7.0=testCompileClasspath,testRuntimeClasspath -org.junit.platform:junit-platform-commons:1.7.0=testCompileClasspath,testRuntimeClasspath -org.junit.platform:junit-platform-engine:1.7.0=testRuntimeClasspath -org.junit.platform:junit-platform-launcher:1.7.0=testRuntimeClasspath -org.junit:junit-bom:5.7.0=testCompileClasspath,testRuntimeClasspath -org.mortbay.jasper:apache-el:8.5.40=testCompileClasspath,testRuntimeClasspath -org.opentest4j:opentest4j:1.2.0=testCompileClasspath,testRuntimeClasspath -org.reactivestreams:reactive-streams:1.0.2=testCompileClasspath,testRuntimeClasspath -org.slf4j:jul-to-slf4j:1.7.28=testCompileClasspath,testRuntimeClasspath -org.slf4j:slf4j-api:1.7.28=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-autoconfigure:2.1.9.RELEASE=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-jetty:2.1.9.RELEASE=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-json:2.1.9.RELEASE=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-logging:2.1.9.RELEASE=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-web:2.1.9.RELEASE=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter:2.1.9.RELEASE=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot:2.1.9.RELEASE=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-aop:5.1.10.RELEASE=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-beans:5.1.10.RELEASE=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-context:5.1.10.RELEASE=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-core:5.1.10.RELEASE=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-expression:5.1.10.RELEASE=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-jcl:5.1.10.RELEASE=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-web:5.1.10.RELEASE=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-webmvc:5.1.10.RELEASE=testCompileClasspath,testRuntimeClasspath -org.yaml:snakeyaml:1.23=testRuntimeClasspath -software.amazon.awssdk:annotations:2.7.19=testCompileClasspath,testRuntimeClasspath -software.amazon.awssdk:apache-client:2.7.19=testRuntimeClasspath -software.amazon.awssdk:auth:2.7.19=testCompileClasspath,testRuntimeClasspath -software.amazon.awssdk:aws-core:2.7.19=testCompileClasspath,testRuntimeClasspath -software.amazon.awssdk:aws-query-protocol:2.7.19=testCompileClasspath,testRuntimeClasspath -software.amazon.awssdk:aws-xml-protocol:2.7.19=testCompileClasspath,testRuntimeClasspath -software.amazon.awssdk:http-client-spi:2.7.19=testCompileClasspath,testRuntimeClasspath -software.amazon.awssdk:netty-nio-client:2.7.19=testRuntimeClasspath -software.amazon.awssdk:profiles:2.7.19=testCompileClasspath,testRuntimeClasspath -software.amazon.awssdk:protocol-core:2.7.19=testCompileClasspath,testRuntimeClasspath -software.amazon.awssdk:regions:2.7.19=testCompileClasspath,testRuntimeClasspath -software.amazon.awssdk:s3:2.7.19=testCompileClasspath,testRuntimeClasspath -software.amazon.awssdk:sdk-core:2.7.19=testCompileClasspath,testRuntimeClasspath -software.amazon.awssdk:url-connection-client:2.7.19=testCompileClasspath,testRuntimeClasspath -software.amazon.awssdk:utils:2.7.19=testCompileClasspath,testRuntimeClasspath -software.amazon.eventstream:eventstream:1.0.1=testCompileClasspath,testRuntimeClasspath -software.amazon.ion:ion-java:1.0.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -empty= diff --git a/ivy/src/main/kotlin/org/nixos/gradle2nix/S3.kt b/ivy/src/main/kotlin/org/nixos/gradle2nix/S3.kt deleted file mode 100644 index 845100d..0000000 --- a/ivy/src/main/kotlin/org/nixos/gradle2nix/S3.kt +++ /dev/null @@ -1,294 +0,0 @@ -package org.nixos.gradle2nix - -import com.amazonaws.AmazonServiceException -import com.amazonaws.ClientConfiguration -import com.amazonaws.auth.AWSCredentials -import com.amazonaws.auth.AWSStaticCredentialsProvider -import com.amazonaws.client.builder.AwsClientBuilder -import com.amazonaws.regions.Region -import com.amazonaws.regions.RegionUtils -import com.amazonaws.regions.Regions -import com.amazonaws.services.s3.AmazonS3 -import com.amazonaws.services.s3.AmazonS3ClientBuilder -import com.amazonaws.services.s3.model.GetObjectRequest -import com.amazonaws.services.s3.model.ListObjectsRequest -import com.amazonaws.services.s3.model.ObjectMetadata -import com.amazonaws.services.s3.model.S3Object -import com.amazonaws.services.s3.model.S3ObjectInputStream -import com.amazonaws.util.AwsHostNameUtils -import org.apache.http.conn.ssl.NoopHostnameVerifier -import org.apache.http.conn.ssl.SSLConnectionSocketFactory -import org.apache.ivy.core.settings.TimeoutConstraint -import org.apache.ivy.plugins.repository.AbstractRepository -import org.apache.ivy.plugins.repository.RepositoryCopyProgressListener -import org.apache.ivy.plugins.repository.Resource -import org.apache.ivy.plugins.repository.TransferEvent -import org.apache.ivy.util.FileUtil -import java.io.File -import java.io.FileOutputStream -import java.io.IOException -import java.io.InputStream -import java.net.Socket -import java.net.URI -import java.security.KeyManagementException -import java.security.NoSuchAlgorithmException -import java.security.SecureRandom -import java.security.cert.X509Certificate -import javax.net.ssl.SSLContext -import javax.net.ssl.SSLEngine -import javax.net.ssl.TrustManager -import javax.net.ssl.X509ExtendedTrustManager - - -class S3Repository( - private val client: AmazonS3, - timeoutConstraint: TimeoutConstraint? = null -) : AbstractRepository(timeoutConstraint) { - - constructor( - credentials: AWSCredentials?, - endpoint: URI?, - timeoutConstraint: TimeoutConstraint? - ) : this( - AmazonS3ClientBuilder.standard().apply { - credentials?.let { setCredentials(AWSStaticCredentialsProvider(it)) } - - if (endpoint != null) { - setEndpointConfiguration( - AwsClientBuilder.EndpointConfiguration( - endpoint.toString(), - AwsHostNameUtils.parseRegion(endpoint.host, null) ?: Regions.US_EAST_1.name - ) - ) - isChunkedEncodingDisabled = true - isPathStyleAccessEnabled = true - } else { - region = Regions.US_EAST_1.name - } - - if (System.getProperty("org.nixos.gradle2nix.s3test") != null) { - clientConfiguration = ClientConfiguration().apply { - apacheHttpClientConfig.sslSocketFactory = SSLConnectionSocketFactory( - createBlindlyTrustingSslContext(), - NoopHostnameVerifier.INSTANCE - ) - } - } - }.build(), - timeoutConstraint - ) - - private val cache = mutableMapOf() - - private val progress = RepositoryCopyProgressListener(this) - - override fun getResource(source: String): Resource = - cache.getOrPut(source) { S3Resource(this, URI(source)) } - - override fun get(source: String, destination: File) { - fireTransferInitiated(getResource(source), TransferEvent.REQUEST_GET) - try { - val res = getResource(source) - val totalLength = res.contentLength - if (totalLength > 0) { - progress.totalLength = totalLength - } - destination.parentFile?.mkdirs() - FileUtil.copy( - res.openStream(), - FileOutputStream(destination), - progress, - true - ) - fireTransferCompleted(res.contentLength) - } catch (e: Exception) { - fireTransferError(e) - throw e - } finally { - progress.totalLength = null - } - } - - override fun list(parent: String): List = - S3Resource(this, URI(parent)) - .let { resource -> - generateSequence({ - try { - withClient(resource) { - listObjects( - ListObjectsRequest() - .withBucketName(resource.bucket) - .withPrefix(resource.key) - .withDelimiter("/") - ) - } - } catch (e: AmazonServiceException) { - throw S3RepositoryException(e) - } - }) { prev -> - if (!prev.isTruncated) { - null - } else { - try { - withClient(resource) { - listNextBatchOfObjects(prev) - } - } catch (e: AmazonServiceException) { - throw S3RepositoryException(e) - } - } - } - } - .flatMap { listing -> - listing.commonPrefixes.asSequence() + - listing.objectSummaries.asSequence().map { it.key } - } - .toList() - - internal fun withClient( - resource: S3Resource, - block: AmazonS3.() -> T - ): T = client.apply { - resource.region?.let { setRegion(it) } - }.block() -} - -class S3Resource( - private val repository: S3Repository, - private val url: URI - ) : Resource { - - private val source: Source by lazy { - REGIONAL_ENDPOINT_PATTERN.find(url.normalize().toString()) - ?.let { - val (bucket, region, _, key) = it.destructured - Source( - bucket = bucket, - key = key, - region = when (region) { - "external-1" -> Region.getRegion(Regions.US_EAST_1) - else -> RegionUtils.getRegion(region) - } - ) - } - ?: Source( - bucket = url.bucket(), - key = url.key(), - region = null - ) - } - - private val metadata: Metadata by lazy { - try { - getMetadata() - } catch (e: AmazonServiceException) { - null - }?.let { meta -> - Metadata( - exists = true, - contentLength = meta.contentLength, - lastModified = meta.lastModified.time - ) - } ?: Metadata( - exists = false, - contentLength = 0, - lastModified = 0 - ) - } - - val bucket: String get() = source.bucket - - val key: String get() = source.key - - val region: Region? get() = source.region - - override fun getName(): String = url.toString() - - override fun getLastModified(): Long = metadata.lastModified - - override fun getContentLength(): Long = metadata.contentLength - - override fun exists(): Boolean = metadata.exists - - override fun isLocal(): Boolean = false - - override fun clone(cloneName: String): Resource = S3Resource(repository, URI(cloneName)) - - override fun openStream(): InputStream = - try { getContent() } - catch (e: AmazonServiceException) { throw S3RepositoryException(e) } - ?: throw S3RepositoryException() - - private fun getMetadata(): ObjectMetadata? = - getObject(withContent = false)?.objectMetadata - - private fun getContent(): S3ObjectInputStream? = - getObject(withContent = true)?.objectContent - - private fun getObject(withContent: Boolean = true): S3Object? { - val request = GetObjectRequest(bucket, key) - if (!withContent) { - request.setRange(0, 0) - } - - return try { - repository.withClient(this) { getObject(request) } - } catch (e: AmazonServiceException) { - val errorCode = e.errorCode - if (errorCode != null && "NoSuchKey".compareTo(errorCode, ignoreCase = true) == 0) { - null - } else { - e.printStackTrace() - throw e - } - } - } - - private data class Source( - val bucket: String, - val key: String, - val region: Region? - ) - - private data class Metadata( - val exists: Boolean, - val contentLength: Long, - val lastModified: Long - ) - - companion object { - private val REGIONAL_ENDPOINT_PATTERN = - Regex("""^s3://(.+)?\.s3[.-]([a-z0-9-]+)\.amazonaws\.com(\.[a-z]+)?/(.+)""") - } -} - -class S3RepositoryException : RuntimeException { - constructor() : super() - - constructor(throwable: Throwable) : super(throwable) -} - -private fun URI.bucket(): String = normalize().host - -private fun URI.key(): String = normalize().path.removePrefix("/") - -// Used for testing. -private fun createBlindlyTrustingSslContext(): SSLContext? { - return try { - SSLContext.getInstance("TLS").apply { - init(null, arrayOf(object : X509ExtendedTrustManager() { - override fun getAcceptedIssuers(): Array? = null - override fun checkClientTrusted(arg0: Array?, arg1: String?, arg2: Socket?) {} - override fun checkClientTrusted(arg0: Array?, arg1: String?, arg2: SSLEngine?) {} - override fun checkClientTrusted(certs: Array?, authType: String?) {} - override fun checkServerTrusted(certs: Array?, authType: String?) {} - override fun checkServerTrusted(arg0: Array?, arg1: String?, arg2: Socket?) {} - override fun checkServerTrusted(arg0: Array?, arg1: String?, arg2: SSLEngine?) {} - }), SecureRandom()) - } - } catch (e: NoSuchAlgorithmException) { - throw RuntimeException("Unexpected exception", e) - } catch (e: KeyManagementException) { - throw RuntimeException("Unexpected exception", e) - } -} diff --git a/ivy/src/test/kotlin/org/nixos/gradle2nix/S3Test.kt b/ivy/src/test/kotlin/org/nixos/gradle2nix/S3Test.kt deleted file mode 100644 index df4a895..0000000 --- a/ivy/src/test/kotlin/org/nixos/gradle2nix/S3Test.kt +++ /dev/null @@ -1,113 +0,0 @@ -package org.nixos.gradle2nix - -import com.adobe.testing.s3mock.junit5.S3MockExtension -import com.amazonaws.services.s3.AmazonS3 -import org.apache.ivy.ant.IvyDependencyArtifact -import org.apache.ivy.core.module.descriptor.Artifact -import org.apache.ivy.core.module.descriptor.DefaultArtifact -import org.apache.ivy.core.module.id.ArtifactRevisionId -import org.apache.ivy.core.module.id.ModuleRevisionId -import org.apache.ivy.core.settings.IvySettings -import org.apache.ivy.plugins.repository.Resource -import org.apache.ivy.plugins.resolver.IBiblioResolver -import org.apache.ivy.plugins.resolver.URLResolver -import org.junit.jupiter.api.BeforeAll -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.TestInstance -import org.junit.jupiter.api.extension.RegisterExtension -import strikt.api.expectThat -import strikt.assertions.containsExactly -import strikt.assertions.isEmpty -import strikt.assertions.isEqualTo -import strikt.assertions.isFalse -import strikt.assertions.isNotEqualTo -import strikt.assertions.isNotNull -import strikt.assertions.isTrue -import java.io.File -import java.net.URI -import kotlin.io.path.ExperimentalPathApi -import kotlin.io.path.createTempDirectory - -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -class S3Test { - companion object { - const val bucket = "repositories" - - val fixtureRoot = File(System.getProperty("fixtures")).resolve(bucket) - - @JvmField - @RegisterExtension - val s3mock: S3MockExtension = S3MockExtension.builder().withInitialBuckets(bucket).build() - } - - @BeforeAll - fun populateBucket(client: AmazonS3) { - fixtureRoot.walkTopDown() - .filter { it.isFile } - .forEach { file -> - val key = file.toRelativeString(fixtureRoot) - client.putObject(bucket, key, file) - } - } - - @Test - fun listsContents(client: AmazonS3) { - val repository = S3Repository(client) - expectThat(repository.list("s3://repositories/m2/org/apache/test/1.0.0/")).containsExactly( - "m2/org/apache/test/1.0.0/test-1.0.0.jar", - "m2/org/apache/test/1.0.0/test-1.0.0.pom", - ) - } - - @Test - fun findsResourceMetadata(client: AmazonS3) { - val repository = S3Repository(client) - val resource: Resource = S3Resource(repository, URI("s3://repositories/m2/org/apache/test/1.0.0/test-1.0.0.pom")) - expectThat(resource).and { - get { exists() }.isTrue() - get { contentLength }.isNotEqualTo(-1L) - get { lastModified }.isNotEqualTo(-1L) - } - } - - @Test - fun downloadsResource(client: AmazonS3) { - val repository = S3Repository(client) - val resource: Resource = S3Resource(repository, URI("s3://repositories/m2/org/apache/test/1.0.0/test-1.0.0.pom")) - val source = fixtureRoot.resolve("m2/org/apache/test/1.0.0/test-1.0.0.pom").readText() - - expectThat(resource.openStream().bufferedReader().readText()).isEqualTo(source) - } - - @ExperimentalPathApi - @Test - fun locatesArtifact(client: AmazonS3) { - val resolver = IBiblioResolver().apply { - name = "s3" - root = "s3://repositories/m2/" - isM2compatible = true - settings = IvySettings().apply { - defaultInit() - setDefaultRepositoryCacheBasedir(createTempDirectory().toString()) - } - repository = S3Repository(client) - } - val origin = resolver.locate(DefaultArtifact( - ArtifactRevisionId.newInstance( - ModuleRevisionId.newInstance("org.apache", "test", "1.0.0"), - "test", - "jar", - "jar" - ), - null, - null, - false - )) - - expectThat(origin).isNotNull().and { - get { isExists }.isTrue() - get { isLocal }.isFalse() - get { location }.isEqualTo("s3://repositories/m2/org/apache/test/1.0.0/test-1.0.0.jar") - } - } -} \ No newline at end of file diff --git a/model/build.gradle.kts b/model/build.gradle.kts index f8a0080..b12db2a 100644 --- a/model/build.gradle.kts +++ b/model/build.gradle.kts @@ -1,10 +1,22 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + plugins { - `embedded-kotlin` - kotlin("kapt") + id("org.jetbrains.kotlin.jvm") + id("org.jetbrains.kotlin.plugin.serialization") } dependencies { - api("com.squareup.moshi:moshi:latest.release") - kapt("com.squareup.moshi:moshi-kotlin-codegen:latest.release") - implementation("net.swiftzer.semver:semver:latest.release") + implementation(libs.serialization.json) + implementation(libs.semver) +} + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + +kotlin { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_1_8) + } } diff --git a/model/gradle.lockfile b/model/gradle.lockfile deleted file mode 100644 index 5d5d7bb..0000000 --- a/model/gradle.lockfile +++ /dev/null @@ -1,13 +0,0 @@ -# This is a Gradle generated file for dependency locking. -# Manual edits can break the build and are not advised. -# This file is expected to be part of source control. -com.squareup.moshi:moshi:1.11.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.squareup.okio:okio:1.17.5=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -net.swiftzer.semver:semver:1.1.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-reflect:1.4.20=compileClasspath,testCompileClasspath,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-common:1.4.20=compileClasspath,testCompileClasspath,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.20=compileClasspath,testCompileClasspath,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.20=compileClasspath,testCompileClasspath,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib:1.4.20=compileClasspath,testCompileClasspath,testRuntimeClasspath -org.jetbrains:annotations:13.0=compileClasspath,testCompileClasspath,testRuntimeClasspath -empty= diff --git a/model/src/main/kotlin/org/nixos/gradle2nix/DependencyCoordinates.kt b/model/src/main/kotlin/org/nixos/gradle2nix/DependencyCoordinates.kt new file mode 100644 index 0000000..2f32f94 --- /dev/null +++ b/model/src/main/kotlin/org/nixos/gradle2nix/DependencyCoordinates.kt @@ -0,0 +1,6 @@ +package org.nixos.gradle2nix.dependencygraph.model + +import kotlinx.serialization.Serializable + +@Serializable +data class DependencyCoordinates(val group: String, val module: String, val version: String) diff --git a/model/src/main/kotlin/org/nixos/gradle2nix/DependencySource.kt b/model/src/main/kotlin/org/nixos/gradle2nix/DependencySource.kt new file mode 100644 index 0000000..18b2767 --- /dev/null +++ b/model/src/main/kotlin/org/nixos/gradle2nix/DependencySource.kt @@ -0,0 +1,13 @@ +package org.nixos.gradle2nix.dependencygraph.model + +import kotlinx.serialization.Serializable + +/** + * The source of a dependency declaration, representing where the direct dependency is declared, + * or where the parent dependency is declared for transitive dependencies. + * In most cases, this will be the project component that declares the dependency, + * but may also be a Version Catalog or the build as a whole. + * We attempt to map this to an actual source file location when building a dependency report. + */ +@Serializable +data class DependencySource(val id: String, val path: String) diff --git a/model/src/main/kotlin/org/nixos/gradle2nix/Impl.kt b/model/src/main/kotlin/org/nixos/gradle2nix/Impl.kt deleted file mode 100644 index c4e4d17..0000000 --- a/model/src/main/kotlin/org/nixos/gradle2nix/Impl.kt +++ /dev/null @@ -1,139 +0,0 @@ -package org.nixos.gradle2nix - -import com.squareup.moshi.JsonClass -import net.swiftzer.semver.SemVer -import java.io.Serializable -import java.lang.IllegalArgumentException - -@JsonClass(generateAdapter = true) -data class DefaultBuild( - override val gradle: DefaultGradle, - override val settingsDependencies: List, - override val pluginDependencies: List, - override val rootProject: DefaultProject, - override val includedBuilds: List -) : Build, Serializable { - constructor(model: Build) : this( - DefaultGradle(model.gradle), - model.settingsDependencies.map(::DefaultArtifact), - model.pluginDependencies.map(::DefaultArtifact), - DefaultProject(model.rootProject), - model.includedBuilds.map(::DefaultIncludedBuild) - ) -} - -@JsonClass(generateAdapter = true) -data class DefaultIncludedBuild( - override val name: String, - override val projectDir: String -) : IncludedBuild, Serializable { - constructor(model: IncludedBuild) : this( - model.name, - model.projectDir - ) -} - -@JsonClass(generateAdapter = true) -data class DefaultGradle( - override val version: String, - override val type: String, - override val url: String, - override val sha256: String, - override val nativeVersion: String -) : Gradle, Serializable { - constructor(model: Gradle) : this( - model.version, - model.type, - model.url, - model.sha256, - model.nativeVersion - ) -} - -@JsonClass(generateAdapter = true) -data class DefaultProject( - override val name: String, - override val version: String, - override val path: String, - override val projectDir: String, - override val buildscriptDependencies: List, - override val projectDependencies: List, - override val children: List -) : Project, Serializable { - constructor(model: Project) : this( - model.name, - model.version, - model.path, - model.projectDir, - model.buildscriptDependencies.map(::DefaultArtifact), - model.projectDependencies.map(::DefaultArtifact), - model.children.map { DefaultProject(it) } - ) -} - -@JsonClass(generateAdapter = true) -data class DefaultArtifact( - override val id: DefaultArtifactIdentifier, - override val name: String, - override val path: String, - override val timestamp: String? = null, - override val build: Int? = null, - override val urls: List, - override val sha256: String -) : Artifact, Comparable, Serializable { - constructor(model: Artifact) : this( - DefaultArtifactIdentifier(model.id), - model.name, - model.path, - model.timestamp, - model.build, - model.urls, - model.sha256 - ) - - override fun toString() = id.toString() - override fun compareTo(other: DefaultArtifact): Int = id.compareTo(other.id) -} - -@JsonClass(generateAdapter = true) -data class DefaultArtifactIdentifier( - override val group: String, - override val name: String, - override val version: String, - override val type: String, - override val extension: String = type, - override val classifier: String? = null -) : ArtifactIdentifier, Comparable, Serializable { - constructor(model: ArtifactIdentifier) : this( - model.group, - model.name, - model.version, - model.type, - model.extension, - model.classifier - ) - - @delegate:Transient - private val semver: SemVer? by lazy { - try { - SemVer.parse(version) - } catch (_: IllegalArgumentException) { - null - } - } - - override fun compareTo(other: DefaultArtifactIdentifier): Int { - return group.compareTo(other.group).takeUnless { it == 0 } - ?: name.compareTo(other.name).takeUnless { it == 0 } - ?: other.semver?.let { semver?.compareTo(it) }?.takeUnless { it == 0 } - ?: type.compareTo(other.type).takeUnless { it == 0 } - ?: other.classifier?.let { classifier?.compareTo(it) }?.takeUnless { it == 0 } - ?: 0 - } - - override fun toString(): String = buildString { - append("$group:$name:$version") - if (classifier != null) append(":$classifier") - append("@$type") - } -} \ No newline at end of file diff --git a/model/src/main/kotlin/org/nixos/gradle2nix/Model.kt b/model/src/main/kotlin/org/nixos/gradle2nix/Model.kt deleted file mode 100644 index 153c051..0000000 --- a/model/src/main/kotlin/org/nixos/gradle2nix/Model.kt +++ /dev/null @@ -1,51 +0,0 @@ -package org.nixos.gradle2nix - -interface Build { - val gradle: Gradle - val settingsDependencies: List - val pluginDependencies: List - val rootProject: Project - val includedBuilds: List -} - -interface IncludedBuild { - val name: String - val projectDir: String -} - -interface Gradle { - val version: String - val type: String - val url: String - val sha256: String - val nativeVersion: String -} - -interface Project { - val name: String - val version: String - val path: String - val projectDir: String - val buildscriptDependencies: List - val projectDependencies: List - val children: List -} - -interface Artifact { - val id: ArtifactIdentifier - val name: String - val path: String - val timestamp: String? - val build: Int? - val urls: List - val sha256: String -} - -interface ArtifactIdentifier { - val group: String - val name: String - val version: String - val type: String - val extension: String - val classifier: String? -} \ No newline at end of file diff --git a/model/src/main/kotlin/org/nixos/gradle2nix/PluginParameters.kt b/model/src/main/kotlin/org/nixos/gradle2nix/PluginParameters.kt new file mode 100644 index 0000000..f98f083 --- /dev/null +++ b/model/src/main/kotlin/org/nixos/gradle2nix/PluginParameters.kt @@ -0,0 +1,7 @@ +package org.nixos.gradle2nix + +const val PARAM_INCLUDE_PROJECTS = "NIX_INCLUDE_PROJECTS" +const val PARAM_INCLUDE_CONFIGURATIONS = "NIX_INCLUDE_CONFIGURATIONS" +const val PARAM_REPORT_DIR = "NIX_REPORT_DIR" +const val RESOLVE_PROJECT_TASK = "resolveProjectDependencies" +const val RESOLVE_ALL_TASK = "resolveAllDependencies" diff --git a/model/src/main/kotlin/org/nixos/gradle2nix/Repository.kt b/model/src/main/kotlin/org/nixos/gradle2nix/Repository.kt new file mode 100644 index 0000000..69659d3 --- /dev/null +++ b/model/src/main/kotlin/org/nixos/gradle2nix/Repository.kt @@ -0,0 +1,20 @@ +package org.nixos.gradle2nix.dependencygraph.model + +import kotlinx.serialization.Serializable + +@Serializable +data class Repository( + val id: String, + val type: Type, + val name: String, + val m2Compatible: Boolean, + val metadataSources: List, + val metadataResources: List, + val artifactResources: List, +) { + enum class Type { + MAVEN, + IVY, + FLAT_DIR + } +} diff --git a/model/src/main/kotlin/org/nixos/gradle2nix/ResolvedConfiguration.kt b/model/src/main/kotlin/org/nixos/gradle2nix/ResolvedConfiguration.kt new file mode 100644 index 0000000..3ff51b5 --- /dev/null +++ b/model/src/main/kotlin/org/nixos/gradle2nix/ResolvedConfiguration.kt @@ -0,0 +1,19 @@ +package org.nixos.gradle2nix.dependencygraph.model + +import kotlinx.serialization.Serializable + +@Serializable +data class ResolvedConfiguration( + val rootSource: DependencySource, + val configurationName: String, + val repositories: List = emptyList(), + val allDependencies: MutableList = mutableListOf() +) { + fun addDependency(component: ResolvedDependency) { + allDependencies.add(component) + } + + fun hasDependency(componentId: String): Boolean { + return allDependencies.any { it.id == componentId } + } +} diff --git a/model/src/main/kotlin/org/nixos/gradle2nix/ResolvedDependency.kt b/model/src/main/kotlin/org/nixos/gradle2nix/ResolvedDependency.kt new file mode 100644 index 0000000..b450e25 --- /dev/null +++ b/model/src/main/kotlin/org/nixos/gradle2nix/ResolvedDependency.kt @@ -0,0 +1,32 @@ +package org.nixos.gradle2nix.dependencygraph.model + +import kotlinx.serialization.Serializable + +// private const val DEFAULT_MAVEN_REPOSITORY_URL = "https://repo.maven.apache.org/maven2" + +@Serializable +data class ResolvedDependency( + val id: String, + val source: DependencySource, + val direct: Boolean, + val coordinates: DependencyCoordinates, + val repository: String?, + val dependencies: List +) +//{ +// fun packageUrl() = +// PackageURLBuilder +// .aPackageURL() +// .withType("maven") +// .withNamespace(coordinates.group.ifEmpty { coordinates.module }) // TODO: This is a sign of broken mapping from component -> PURL +// .withName(coordinates.module) +// .withVersion(coordinates.version) +// .also { +// if (repositoryUrl != null && repositoryUrl != DEFAULT_MAVEN_REPOSITORY_URL) { +// it.withQualifier("repository_url", repositoryUrl) +// } +// } +// .build() +// .toString() +// +//} diff --git a/plugin/.stutter/java11.lock b/plugin/.stutter/java11.lock deleted file mode 100644 index 9717484..0000000 --- a/plugin/.stutter/java11.lock +++ /dev/null @@ -1,5 +0,0 @@ -# DO NOT MODIFY: Generated by Stutter plugin. -5.0 -5.6.4 -6.0.1 -6.8.1 diff --git a/plugin/.stutter/java8.lock b/plugin/.stutter/java8.lock deleted file mode 100644 index db50dba..0000000 --- a/plugin/.stutter/java8.lock +++ /dev/null @@ -1,7 +0,0 @@ -# DO NOT MODIFY: Generated by Stutter plugin. -4.4.1 -4.10.3 -5.0 -5.6.4 -6.0.1 -6.8.1 diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index c59e544..915e72c 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -1,52 +1,29 @@ -buildscript { - configurations.classpath { - resolutionStrategy.activateDependencyLocking() - } -} +import com.github.jengelman.gradle.plugins.shadow.relocation.SimpleRelocator +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.utils.extendsFrom plugins { - `kotlin-dsl` + id("org.jetbrains.kotlin.jvm") + id("com.gradle.plugin-publish") id("com.github.johnrengelman.shadow") - id("org.ajoberstar.stutter") -} - -sourceSets { - test { - java.srcDir("src/test/kotlin") - } -} - -dependencyLocking { - lockAllConfigurations() -} - -configurations { - compile { - dependencies.remove(project.dependencies.gradleApi()) - } } dependencies { - compileOnly("org.gradle:gradle-tooling-api:${gradle.gradleVersion}") - implementation("org.apache.maven:maven-repository-metadata:latest.release") - implementation(project(":ivy")) + compileOnly(kotlin("stdlib-jdk8")) + compileOnly(kotlin("reflect")) implementation(project(":model")) - shadow(gradleApi()) + implementation(libs.serialization.json) +} - compatTestImplementation("com.adobe.testing:s3mock-junit5:latest.release") - compatTestImplementation("com.squareup.okio:okio:latest.release") - compatTestImplementation("dev.minutest:minutest:latest.release") - compatTestImplementation("io.javalin:javalin:latest.release") - compatTestImplementation("io.strikt:strikt-core:latest.release") - compatTestImplementation("org.junit.jupiter:junit-jupiter-api:latest.release") - compatTestImplementation("org.junit.jupiter:junit-jupiter-params:latest.release") - compatTestImplementation(embeddedKotlin("reflect")) - compatTestImplementation(embeddedKotlin("stdlib-jdk8")) - compatTestImplementation(embeddedKotlin("test-junit5")) - compatTestImplementation(gradleTestKit()) - compatTestImplementation(project(":model")) - compatTestRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:latest.release") - compatTestRuntimeOnly("org.junit.platform:junit-platform-launcher:latest.release") +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + +kotlin { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_1_8) + } } gradlePlugin { @@ -60,35 +37,25 @@ gradlePlugin { } } -kotlinDslPluginOptions { - experimentalWarning.set(false) -} - -stutter { - isSparse = true - java(8) { - compatibleRange("4.4") - } - java(11) { - compatibleRange("5.0") - } -} - tasks { - pluginUnderTestMetadata { - pluginClasspath.setFrom(files(shadowJar)) + jar { + manifest { + attributes["Implementation-Version"] = archiveVersion.get() + attributes["Implementation-Title"] = "Gradle2Nix Plugin" + attributes["Implementation-Vendor"] = "Tad Fisher" + } } - withType { - useJUnitPlatform { - includeEngines("junit-jupiter") - } + shadowJar { + archiveClassifier.set("") + relocate("kotlin", "${project.group}.shadow.kotlin") + relocate("kotlinx.serialization", "${project.group}.shadow.serialization") + relocate("net.swiftzer.semver", "${project.group}.shadow.semver") + relocate("org.intellij", "${project.group}.shadow.intellij") + relocate("org.jetbrains", "${project.group}.shadow.jetbrains") + } - // Default logging config exposes a classpath conflict between - // the Gradle API and SFL4J. - // (Sprint Boot is used in S3Mock) - systemProperty("org.springframework.boot.logging.LoggingSystem", "org.springframework.boot.logging.java.JavaLoggingSystem") - - systemProperty("fixtures", "$rootDir/fixtures") + validatePlugins { + enableStricterValidation.set(true) } } diff --git a/plugin/buildscript-gradle.lockfile b/plugin/buildscript-gradle.lockfile deleted file mode 100644 index 99b963e..0000000 --- a/plugin/buildscript-gradle.lockfile +++ /dev/null @@ -1,36 +0,0 @@ -# This is a Gradle generated file for dependency locking. -# Manual edits can break the build and are not advised. -# This file is expected to be part of source control. -com.github.gundy:semver4j:0.16.4=classpath -com.google.code.gson:gson:2.8.6=classpath -de.undercouch:gradle-download-task:4.0.2=classpath -org.antlr:antlr4-runtime:4.5.2-1=classpath -org.gradle.kotlin.kotlin-dsl:org.gradle.kotlin.kotlin-dsl.gradle.plugin:1.4.9=classpath -org.gradle.kotlin:gradle-kotlin-dsl-plugins:1.4.9=classpath -org.jetbrains.intellij.deps:trove4j:1.0.20181211=classpath -org.jetbrains.kotlin:kotlin-android-extensions:1.4.20=classpath -org.jetbrains.kotlin:kotlin-annotation-processing-gradle:1.4.20=classpath -org.jetbrains.kotlin:kotlin-build-common:1.4.20=classpath -org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.20=classpath -org.jetbrains.kotlin:kotlin-compiler-runner:1.4.20=classpath -org.jetbrains.kotlin:kotlin-daemon-client:1.4.20=classpath -org.jetbrains.kotlin:kotlin-daemon-embeddable:1.4.20=classpath -org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.4.20=classpath -org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.4.20=classpath -org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.20=classpath -org.jetbrains.kotlin:kotlin-reflect:1.4.20=classpath -org.jetbrains.kotlin:kotlin-sam-with-receiver:1.4.20=classpath -org.jetbrains.kotlin:kotlin-script-runtime:1.4.20=classpath -org.jetbrains.kotlin:kotlin-scripting-common:1.4.20=classpath -org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.4.20=classpath -org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.4.20=classpath -org.jetbrains.kotlin:kotlin-scripting-jvm:1.4.20=classpath -org.jetbrains.kotlin:kotlin-stdlib-common:1.4.20=classpath -org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.20=classpath -org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.20=classpath -org.jetbrains.kotlin:kotlin-stdlib:1.4.20=classpath -org.jetbrains.kotlin:kotlin-util-io:1.4.20=classpath -org.jetbrains.kotlin:kotlin-util-klib:1.4.20=classpath -org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7=classpath -org.jetbrains:annotations:13.0=classpath -empty= diff --git a/plugin/gradle.lockfile b/plugin/gradle.lockfile deleted file mode 100644 index d1cb2b7..0000000 --- a/plugin/gradle.lockfile +++ /dev/null @@ -1,170 +0,0 @@ -# This is a Gradle generated file for dependency locking. -# Manual edits can break the build and are not advised. -# This file is expected to be part of source control. -ch.qos.logback:logback-classic:1.2.3=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -ch.qos.logback:logback-core:1.2.3=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -com.adobe.testing:s3mock-junit5:2.1.28=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -com.adobe.testing:s3mock-testsupport-common:2.1.28=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -com.adobe.testing:s3mock:2.1.28=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -com.amazonaws:aws-java-sdk-core:1.11.488=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -com.amazonaws:aws-java-sdk-core:1.11.946=compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -com.amazonaws:aws-java-sdk-kms:1.11.488=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -com.amazonaws:aws-java-sdk-kms:1.11.946=compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -com.amazonaws:aws-java-sdk-s3:1.11.488=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -com.amazonaws:aws-java-sdk-s3:1.11.946=compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -com.amazonaws:jmespath-java:1.11.488=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -com.amazonaws:jmespath-java:1.11.946=compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -com.christophsturm:filepeek:0.1.2=compatTestRuntimeClasspath -com.fasterxml.jackson.core:jackson-annotations:2.6.0=compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-annotations:2.9.0=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -com.fasterxml.jackson.core:jackson-core:2.6.7=compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-core:2.9.9=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -com.fasterxml.jackson.core:jackson-databind:2.6.7.4=compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-databind:2.9.9.3=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.6.7=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath,compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.9=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.9.9=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.9=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.9.9=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -com.fasterxml.jackson.module:jackson-module-parameter-names:2.9.9=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -com.fasterxml.woodstox:woodstox-core:5.1.0=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -com.fasterxml:classmate:1.3.4=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -com.squareup.moshi:moshi:1.11.0=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath,compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -com.squareup.okio:okio-metadata:3.0.0-alpha.1=compatTestImplementationDependenciesMetadata -com.squareup.okio:okio:1.17.5=compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -com.squareup.okio:okio:3.0.0-alpha.1=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -com.typesafe.netty:netty-reactive-streams-http:2.0.0=compatTestRuntimeClasspath -com.typesafe.netty:netty-reactive-streams:2.0.0=compatTestRuntimeClasspath -commons-codec:commons-codec:1.11=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath,compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -commons-io:commons-io:2.6=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -commons-logging:commons-logging:1.2=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath,compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -dev.minutest:minutest:2.0.0-alpha=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -io.github.classgraph:classgraph:4.8.28=compatTestRuntimeClasspath -io.javalin:javalin:3.13.3=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -io.netty:netty-buffer:4.1.33.Final=compatTestRuntimeClasspath -io.netty:netty-codec-http2:4.1.33.Final=compatTestRuntimeClasspath -io.netty:netty-codec-http:4.1.33.Final=compatTestRuntimeClasspath -io.netty:netty-codec:4.1.33.Final=compatTestRuntimeClasspath -io.netty:netty-common:4.1.33.Final=compatTestRuntimeClasspath -io.netty:netty-handler:4.1.33.Final=compatTestRuntimeClasspath -io.netty:netty-resolver:4.1.33.Final=compatTestRuntimeClasspath -io.netty:netty-transport-native-epoll:4.1.33.Final=compatTestRuntimeClasspath -io.netty:netty-transport-native-unix-common:4.1.33.Final=compatTestRuntimeClasspath -io.netty:netty-transport:4.1.33.Final=compatTestRuntimeClasspath -io.strikt:strikt-core:0.28.2=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -javax.annotation:javax.annotation-api:1.3.2=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -javax.servlet:javax.servlet-api:3.1.0=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -javax.validation:validation-api:2.0.1.Final=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -joda-time:joda-time:2.8.1=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath,compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -net.swiftzer.semver:semver:1.1.1=compatTestRuntimeClasspath,default,runtimeClasspath,testRuntimeClasspath -org.apache.commons:commons-lang3:3.8.1=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.13=compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.5=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata -org.apache.httpcomponents:httpclient:4.5.9=compatTestRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.11=compatTestRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.13=compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.9=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata -org.apache.ivy:ivy:2.5.0=compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.apache.logging.log4j:log4j-api:2.11.2=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.apache.logging.log4j:log4j-to-slf4j:2.11.2=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.apache.maven:maven-repository-metadata:3.6.3=compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.apiguardian:apiguardian-api:1.1.0=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath,compatTestRuntimeOnlyDependenciesMetadata -org.codehaus.plexus:plexus-utils:3.2.1=compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.codehaus.woodstox:stax2-api:4.1=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.eclipse.jetty.websocket:websocket-api:9.4.35.v20201120=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.eclipse.jetty.websocket:websocket-client:9.4.35.v20201120=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.eclipse.jetty.websocket:websocket-common:9.4.35.v20201120=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.eclipse.jetty.websocket:websocket-server:9.4.35.v20201120=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.eclipse.jetty.websocket:websocket-servlet:9.4.35.v20201120=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.eclipse.jetty:jetty-client:9.4.35.v20201120=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.eclipse.jetty:jetty-continuation:9.4.19.v20190610=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.eclipse.jetty:jetty-http:9.4.35.v20201120=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.eclipse.jetty:jetty-io:9.4.35.v20201120=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.eclipse.jetty:jetty-security:9.4.35.v20201120=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.eclipse.jetty:jetty-server:9.4.35.v20201120=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.eclipse.jetty:jetty-servlet:9.4.35.v20201120=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.eclipse.jetty:jetty-servlets:9.4.19.v20190610=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.eclipse.jetty:jetty-util-ajax:9.4.35.v20201120=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.eclipse.jetty:jetty-util:9.4.35.v20201120=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.eclipse.jetty:jetty-webapp:9.4.35.v20201120=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.eclipse.jetty:jetty-xml:9.4.35.v20201120=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.gradle:gradle-tooling-api:6.8.1=compileClasspath,compileOnly,compileOnlyDependenciesMetadata -org.hibernate.validator:hibernate-validator:6.0.17.Final=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.jboss.logging:jboss-logging:3.3.2.Final=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.jetbrains.intellij.deps:trove4j:1.0.20181211=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath -org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.20=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath -org.jetbrains.kotlin:kotlin-daemon-embeddable:1.4.20=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath -org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.4.20=kotlinCompilerPluginClasspath -org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.4.20=kotlinCompilerPluginClasspath -org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:1.4.20=kotlinKlibCommonizerClasspath -org.jetbrains.kotlin:kotlin-reflect:1.4.20=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compileClasspath,compileOnly,compileOnlyDependenciesMetadata,embeddedKotlin,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-reflect:1.4.21-2=compatTestRuntimeClasspath -org.jetbrains.kotlin:kotlin-sam-with-receiver:1.4.20=kotlinCompilerPluginClasspath -org.jetbrains.kotlin:kotlin-script-runtime:1.4.20=kotlinCompilerClasspath,kotlinCompilerPluginClasspath,kotlinKlibCommonizerClasspath -org.jetbrains.kotlin:kotlin-scripting-common:1.4.20=kotlinCompilerPluginClasspath -org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.4.20=kotlinCompilerPluginClasspath -org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.4.20=kotlinCompilerPluginClasspath -org.jetbrains.kotlin:kotlin-scripting-jvm:1.4.20=kotlinCompilerPluginClasspath -org.jetbrains.kotlin:kotlin-stdlib-common:1.4.20=compileClasspath,compileOnly,compileOnlyDependenciesMetadata,default,embeddedKotlin,implementationDependenciesMetadata,kotlinCompilerClasspath,kotlinCompilerPluginClasspath,kotlinKlibCommonizerClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-common:1.4.21-2=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.20=compileClasspath,compileOnly,compileOnlyDependenciesMetadata,embeddedKotlin,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.21-2=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.20=compileClasspath,compileOnly,compileOnlyDependenciesMetadata,embeddedKotlin,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.21-2=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib:1.4.20=compileClasspath,compileOnly,compileOnlyDependenciesMetadata,default,embeddedKotlin,implementationDependenciesMetadata,kotlinCompilerClasspath,kotlinCompilerPluginClasspath,kotlinKlibCommonizerClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib:1.4.21-2=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.jetbrains.kotlin:kotlin-test-annotations-common:1.4.20=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.jetbrains.kotlin:kotlin-test-common:1.4.20=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.jetbrains.kotlin:kotlin-test-junit5:1.4.20=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.jetbrains.kotlin:kotlin-test:1.4.20=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.4.2=compatTestRuntimeClasspath -org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7=kotlinCompilerPluginClasspath -org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2=compatTestRuntimeClasspath -org.jetbrains:annotations:13.0=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath,compileClasspath,compileOnly,compileOnlyDependenciesMetadata,default,embeddedKotlin,implementationDependenciesMetadata,kotlinCompilerClasspath,kotlinCompilerPluginClasspath,kotlinKlibCommonizerClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.junit.jupiter:junit-jupiter-api:5.7.0=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath,compatTestRuntimeOnlyDependenciesMetadata -org.junit.jupiter:junit-jupiter-engine:5.7.0=compatTestRuntimeClasspath,compatTestRuntimeOnlyDependenciesMetadata -org.junit.jupiter:junit-jupiter-params:5.7.0=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.junit.platform:junit-platform-commons:1.7.0=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath,compatTestRuntimeOnlyDependenciesMetadata -org.junit.platform:junit-platform-engine:1.7.0=compatTestRuntimeClasspath,compatTestRuntimeOnlyDependenciesMetadata -org.junit.platform:junit-platform-launcher:1.7.0=compatTestRuntimeClasspath,compatTestRuntimeOnlyDependenciesMetadata -org.junit:junit-bom:5.7.0=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath,compatTestRuntimeOnlyDependenciesMetadata -org.mortbay.jasper:apache-el:8.5.40=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.opentest4j:opentest4j:1.2.0=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath,compatTestRuntimeOnlyDependenciesMetadata -org.reactivestreams:reactive-streams:1.0.2=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.slf4j:jul-to-slf4j:1.7.28=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.slf4j:slf4j-api:1.7.28=compileClasspath,compileOnly,compileOnlyDependenciesMetadata -org.slf4j:slf4j-api:1.7.30=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.springframework.boot:spring-boot-autoconfigure:2.1.9.RELEASE=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.springframework.boot:spring-boot-starter-jetty:2.1.9.RELEASE=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.springframework.boot:spring-boot-starter-json:2.1.9.RELEASE=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.springframework.boot:spring-boot-starter-logging:2.1.9.RELEASE=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.springframework.boot:spring-boot-starter-web:2.1.9.RELEASE=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.springframework.boot:spring-boot-starter:2.1.9.RELEASE=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.springframework.boot:spring-boot:2.1.9.RELEASE=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.springframework:spring-aop:5.1.10.RELEASE=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.springframework:spring-beans:5.1.10.RELEASE=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.springframework:spring-context:5.1.10.RELEASE=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.springframework:spring-core:5.1.10.RELEASE=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.springframework:spring-expression:5.1.10.RELEASE=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.springframework:spring-jcl:5.1.10.RELEASE=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.springframework:spring-web:5.1.10.RELEASE=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.springframework:spring-webmvc:5.1.10.RELEASE=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -org.yaml:snakeyaml:1.23=compatTestRuntimeClasspath -software.amazon.awssdk:annotations:2.7.19=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -software.amazon.awssdk:apache-client:2.7.19=compatTestRuntimeClasspath -software.amazon.awssdk:auth:2.7.19=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -software.amazon.awssdk:aws-core:2.7.19=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -software.amazon.awssdk:aws-query-protocol:2.7.19=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -software.amazon.awssdk:aws-xml-protocol:2.7.19=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -software.amazon.awssdk:http-client-spi:2.7.19=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -software.amazon.awssdk:netty-nio-client:2.7.19=compatTestRuntimeClasspath -software.amazon.awssdk:profiles:2.7.19=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -software.amazon.awssdk:protocol-core:2.7.19=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -software.amazon.awssdk:regions:2.7.19=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -software.amazon.awssdk:s3:2.7.19=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -software.amazon.awssdk:sdk-core:2.7.19=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -software.amazon.awssdk:url-connection-client:2.7.19=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -software.amazon.awssdk:utils:2.7.19=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -software.amazon.eventstream:eventstream:1.0.1=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath -software.amazon.ion:ion-java:1.0.2=compatTestCompileClasspath,compatTestImplementationDependenciesMetadata,compatTestRuntimeClasspath,compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -empty=annotationProcessor,apiDependenciesMetadata,archives,compatTestAnnotationProcessor,compatTestApiDependenciesMetadata,compatTestCompile,compatTestCompileOnly,compatTestCompileOnlyDependenciesMetadata,compatTestKotlinScriptDef,compatTestKotlinScriptDefExtensions,compatTestRuntime,compile,kotlinNativeCompilerPluginClasspath,kotlinScriptDef,kotlinScriptDefExtensions,runtime,runtimeOnlyDependenciesMetadata,shadow,testAnnotationProcessor,testApiDependenciesMetadata,testCompile,testCompileOnly,testCompileOnlyDependenciesMetadata,testKotlinScriptDef,testKotlinScriptDefExtensions,testRuntime,testRuntimeOnlyDependenciesMetadata diff --git a/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/BasicTest.kt b/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/BasicTest.kt deleted file mode 100644 index 3d3e833..0000000 --- a/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/BasicTest.kt +++ /dev/null @@ -1,74 +0,0 @@ -package org.nixos.gradle2nix - -import dev.minutest.Tests -import dev.minutest.experimental.minus -import dev.minutest.junit.JUnit5Minutests -import dev.minutest.rootContext -import dev.minutest.test -import org.gradle.api.internal.artifacts.dsl.DefaultRepositoryHandler.BINTRAY_JCENTER_URL -import org.gradle.api.internal.artifacts.dsl.DefaultRepositoryHandler.MAVEN_CENTRAL_URL -import strikt.api.expectThat -import strikt.assertions.all -import strikt.assertions.containsExactly -import strikt.assertions.flatMap -import strikt.assertions.get -import strikt.assertions.hasSize -import strikt.assertions.isEqualTo -import strikt.assertions.map -import strikt.assertions.none -import strikt.assertions.startsWith - -class BasicTest : JUnit5Minutests { - @Tests - fun tests() = rootContext("basic tests") { - withFixture("basic/basic-java-project") { - test("builds basic java project") { - expectThat(build()) { - get("gradle version") { gradle.version }.isEqualTo(System.getProperty("compat.gradle.version")) - - get("all dependencies") { - pluginDependencies + - rootProject.buildscriptDependencies + - rootProject.projectDependencies - }.flatMap { it.urls }.none { startsWith("file:") } - - get("root project dependencies") { rootProject.projectDependencies }.and { - ids.containsExactly( - "com.squareup.moshi:moshi:1.8.0@jar", - "com.squareup.moshi:moshi:1.8.0@pom", - "com.squareup.moshi:moshi-parent:1.8.0@pom", - "com.squareup.okio:okio:2.2.2@jar", - "com.squareup.okio:okio:2.2.2@pom", - "org.jetbrains:annotations:13.0@jar", - "org.jetbrains:annotations:13.0@pom", - "org.jetbrains.kotlin:kotlin-stdlib:1.2.60@jar", - "org.jetbrains.kotlin:kotlin-stdlib:1.2.60@pom", - "org.jetbrains.kotlin:kotlin-stdlib-common:1.2.60@jar", - "org.jetbrains.kotlin:kotlin-stdlib-common:1.2.60@pom", - "org.sonatype.oss:oss-parent:7@pom" - ) - - map { it.urls }.all { - hasSize(2) - get(0).startsWith(BINTRAY_JCENTER_URL) - get(1).startsWith(MAVEN_CENTRAL_URL) - } - } - } - } - } - - withFixture("basic/basic-kotlin-project") { - GRADLE_MIN("4.9") - test("excludes embedded kotlin repo") { - - expectThat(build()) { - get("all dependencies") { - pluginDependencies + - rootProject.buildscriptDependencies + - rootProject.projectDependencies - }.flatMap { it.urls }.all { not { startsWith("file:") } } - } - } - } - } -} diff --git a/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/DependencyTest.kt b/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/DependencyTest.kt deleted file mode 100644 index cd60aa7..0000000 --- a/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/DependencyTest.kt +++ /dev/null @@ -1,102 +0,0 @@ -package org.nixos.gradle2nix - -import dev.minutest.Tests -import dev.minutest.experimental.minus -import dev.minutest.junit.JUnit5Minutests -import dev.minutest.rootContext -import dev.minutest.test -import strikt.api.expectThat -import strikt.assertions.all -import strikt.assertions.containsExactly -import strikt.assertions.filter -import strikt.assertions.isEqualTo -import strikt.assertions.isNotNull -import strikt.assertions.isNull - -class DependencyTest : JUnit5Minutests { - @Tests - fun tests() = rootContext("dependency tests") { - - withRepository("m2") { - - withFixture("dependency/classifier") { - test("resolves dependency with classifier") { - expectThat(build()) { - get("root project dependencies") { rootProject.projectDependencies }.ids.containsExactly( - "com.badlogicgames.gdx:gdx-parent:1.9.9@pom", - "com.badlogicgames.gdx:gdx-platform:1.9.9:natives-desktop@jar", - "com.badlogicgames.gdx:gdx-platform:1.9.9@pom", - "org.sonatype.oss:oss-parent:5@pom" - ) - } - } - } - - withFixture("dependency/maven-bom") { - GRADLE_MIN("5.0") - test("resolves dependencies from maven bom platform") { - expectThat(build()) { - get("root project dependencies") { rootProject.projectDependencies } - .ids - .containsExactly( - "io.micrometer:micrometer-bom:1.5.1@pom", - "io.micrometer:micrometer-core:1.5.1@jar", - "io.micrometer:micrometer-core:1.5.1@pom", - "org.hdrhistogram:HdrHistogram:2.1.12@jar", - "org.hdrhistogram:HdrHistogram:2.1.12@pom" - ) - } - } - } - - withFixture("dependency/snapshot") { - test("resolves snapshot dependency") { - expectThat(build()) { - get("root project dependencies") { rootProject.projectDependencies } - .and { - ids.containsExactly( - "org.apache:test-SNAPSHOT2:2.0.2-SNAPSHOT@jar", - "org.apache:test-SNAPSHOT2:2.0.2-SNAPSHOT@pom" - ) - all { - get("timestamp") { timestamp }.isNull() - get("build") { build }.isNotNull() - } - } - } - } - } - - withFixture("dependency/snapshot-dynamic") { - test("resolves snapshot dependency with dynamic version") { - expectThat(build()) { - get("root project dependencies") { rootProject.projectDependencies } - .and { - ids.containsExactly( - "org.apache:test-SNAPSHOT1:2.0.2-SNAPSHOT@jar", - "org.apache:test-SNAPSHOT1:2.0.2-SNAPSHOT@pom" - ) - all { - get("timestamp") { timestamp }.isEqualTo("20070310.181613") - get("build") { build }.isEqualTo(3) - } - } - } - } - } - - withFixture("dependency/snapshot-redirect") { - test("resolves snapshot dependency with redirect") { - expectThat(build()) { - get("root project dependencies") { rootProject.projectDependencies } - .filter { it.id.name == "packr" } - .all { - get("id.version") { id.version }.isEqualTo("-SNAPSHOT") - get("timestamp") { timestamp }.isNotNull() - get("build") { build }.isNotNull() - } - } - } - } - } - } -} \ No newline at end of file diff --git a/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/IvyTest.kt b/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/IvyTest.kt deleted file mode 100644 index 3269ce3..0000000 --- a/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/IvyTest.kt +++ /dev/null @@ -1,34 +0,0 @@ -package org.nixos.gradle2nix - -import dev.minutest.Tests -import dev.minutest.junit.JUnit5Minutests -import dev.minutest.rootContext -import dev.minutest.test -import strikt.api.expectThat -import strikt.assertions.all -import strikt.assertions.containsExactly -import strikt.assertions.map -import strikt.assertions.single -import strikt.assertions.startsWith - -class IvyTest : JUnit5Minutests { - @Tests - fun tests() = rootContext("ivy tests") { - withFixture("ivy/basic") { - test("resolves ivy dependencies") { - expectThat(build()) { - get("root project dependencies") { rootProject.projectDependencies }.and { - ids.containsExactly( - "org.opendof.core-java:dof-cipher-sms4:1.0@jar", - "org.opendof.core-java:dof-oal:7.0.2@jar" - ) - - map { it.urls }.all { - single().startsWith("https://asset.opendof.org/artifact") - } - } - } - } - } - } -} \ No newline at end of file diff --git a/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/PluginTest.kt b/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/PluginTest.kt deleted file mode 100644 index 961f505..0000000 --- a/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/PluginTest.kt +++ /dev/null @@ -1,25 +0,0 @@ -package org.nixos.gradle2nix - -import dev.minutest.Tests -import dev.minutest.experimental.FOCUS -import dev.minutest.experimental.minus -import dev.minutest.junit.JUnit5Minutests -import dev.minutest.rootContext -import dev.minutest.test -import strikt.api.expectThat -import strikt.assertions.contains -import strikt.assertions.containsExactly - -class PluginTest : JUnit5Minutests { - @Tests - fun tests() = rootContext("plugin tests") { - withFixture("plugin/resolves-from-default-repo") { - test("resolves plugin from default repo") { - expectThat(build()) { - get("plugin dependencies") { pluginDependencies }.ids - .contains("org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.3.50@pom") - } - } - } - } -} \ No newline at end of file diff --git a/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/S3Test.kt b/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/S3Test.kt deleted file mode 100644 index f72c79c..0000000 --- a/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/S3Test.kt +++ /dev/null @@ -1,52 +0,0 @@ -package org.nixos.gradle2nix - -import dev.minutest.Tests -import dev.minutest.junit.JUnit5Minutests -import dev.minutest.rootContext -import dev.minutest.test -import strikt.api.expectThat -import strikt.assertions.containsExactly -import strikt.assertions.flatMap -import strikt.assertions.map - -class S3Test : JUnit5Minutests { - @Tests - fun tests() = rootContext("s3 tests") { - withBucket("repositories") { - withFixture("s3/maven") { - - test("dependency from s3 maven repo") { - expectThat(build()) { - get("root project dependencies") { rootProject.projectDependencies }.and { - ids.containsExactly( - "org.apache:test:1.0.0@jar", - "org.apache:test:1.0.0@pom" - ) - flatMap { it.urls }.containsExactly( - "s3://repositories/m2/org/apache/test/1.0.0/test-1.0.0.jar", - "s3://repositories/m2/org/apache/test/1.0.0/test-1.0.0.pom" - ) - } - } - } - } - - withFixture("s3/maven-snapshot") { - test("snapshot dependency from s3 maven repo") { - expectThat(build()) { - get("root project dependencies") { rootProject.projectDependencies }.and { - ids.containsExactly( - "org.apache:test-SNAPSHOT1:2.0.0-SNAPSHOT@jar", - "org.apache:test-SNAPSHOT1:2.0.0-SNAPSHOT@pom" - ) - flatMap { it.urls }.containsExactly( - "s3://repositories/m2/org/apache/test-SNAPSHOT1/2.0.0-SNAPSHOT/test-SNAPSHOT1-2.0.0-20070310.181613-3.jar", - "s3://repositories/m2/org/apache/test-SNAPSHOT1/2.0.0-SNAPSHOT/test-SNAPSHOT1-2.0.0-20070310.181613-3.pom" - ) - } - } - } - } - } - } -} \ No newline at end of file diff --git a/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/SettingsTest.kt b/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/SettingsTest.kt deleted file mode 100644 index aaf089f..0000000 --- a/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/SettingsTest.kt +++ /dev/null @@ -1,39 +0,0 @@ -package org.nixos.gradle2nix - -import dev.minutest.Tests -import dev.minutest.experimental.minus -import dev.minutest.junit.JUnit5Minutests -import dev.minutest.rootContext -import dev.minutest.test -import strikt.api.expectThat -import strikt.assertions.containsExactly - -class SettingsTest : JUnit5Minutests { - @Tests - fun tests() = rootContext("settings tests") { - withRepository("m2") { - - withFixture("settings/buildscript") { - test("resolves settings plugin in buildscript classpath") { - expectThat(build()) { - get("settings dependencies") { settingsDependencies }.ids.containsExactly( - "org.apache:test:1.0.0@jar", - "org.apache:test:1.0.0@pom" - ) - } - } - } - - withFixture("settings/dependency-resolution-management") { - GRADLE_MIN("6.8") - test("uses repositories from settings script") { - expectThat(build()) { - get("root project dependencies") { rootProject.projectDependencies }.ids.containsExactly( - "org.apache:test:1.0.0@jar", - "org.apache:test:1.0.0@pom" - ) - } - } - } - } - } -} \ No newline at end of file diff --git a/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/SubprojectsTest.kt b/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/SubprojectsTest.kt deleted file mode 100644 index f0bed36..0000000 --- a/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/SubprojectsTest.kt +++ /dev/null @@ -1,152 +0,0 @@ -package org.nixos.gradle2nix - -import dev.minutest.Tests -import dev.minutest.junit.JUnit5Minutests -import dev.minutest.rootContext -import dev.minutest.test -import org.gradle.api.internal.artifacts.dsl.DefaultRepositoryHandler.BINTRAY_JCENTER_URL -import strikt.api.expectThat -import strikt.assertions.all -import strikt.assertions.containsExactly -import strikt.assertions.containsExactlyInAnyOrder -import strikt.assertions.get -import strikt.assertions.hasSize -import strikt.assertions.isEqualTo -import strikt.assertions.map -import strikt.assertions.single -import strikt.assertions.startsWith - -class SubprojectsTest : JUnit5Minutests { - @Tests - fun tests() = rootContext("subproject tests") { - withFixture("subprojects/multi-module") { - test("builds multi-module project") { - expectThat(build().rootProject) { - get("root project dependencies") { projectDependencies }.and { - ids.containsExactly( - "junit:junit:4.12@jar", - "junit:junit:4.12@pom", - "org.hamcrest:hamcrest-core:1.3@jar", - "org.hamcrest:hamcrest-core:1.3@pom", - "org.hamcrest:hamcrest-parent:1.3@pom" - ) - all { - get("urls") { urls }.single().startsWith(BINTRAY_JCENTER_URL) - } - } - - get("children") { children }.and { - hasSize(2) - - get(0).and { - get("name") { name }.isEqualTo("child-a") - get("projectDir") { projectDir }.isEqualTo("child-a") - - get("child-a project dependencies") { projectDependencies }.and { - ids.containsExactly( - "com.squareup.okio:okio:2.2.2@jar", - "com.squareup.okio:okio:2.2.2@pom", - "org.jetbrains:annotations:13.0@jar", - "org.jetbrains:annotations:13.0@pom", - "org.jetbrains.kotlin:kotlin-stdlib:1.2.60@jar", - "org.jetbrains.kotlin:kotlin-stdlib:1.2.60@pom", - "org.jetbrains.kotlin:kotlin-stdlib-common:1.2.60@jar", - "org.jetbrains.kotlin:kotlin-stdlib-common:1.2.60@pom" - ) - - all { - get("urls") { urls }.single().startsWith(BINTRAY_JCENTER_URL) - } - } - } - - get(1).and { - get("name") { name }.isEqualTo("child-b") - get("projectDir") { projectDir }.isEqualTo("child-b") - - get("child-b project dependencies") { projectDependencies }.and { - ids.containsExactly( - "com.squareup.moshi:moshi:1.8.0@jar", - "com.squareup.moshi:moshi:1.8.0@pom", - "com.squareup.moshi:moshi-parent:1.8.0@pom", - "com.squareup.okio:okio:1.16.0@jar", // compileClasspath - "com.squareup.okio:okio:1.16.0@pom", // compileClasspath - "com.squareup.okio:okio:2.2.2@jar", // runtimeClasspath - "com.squareup.okio:okio:2.2.2@pom", // runtimeClasspath - "com.squareup.okio:okio-parent:1.16.0@pom", // compileClasspath - "org.jetbrains:annotations:13.0@jar", - "org.jetbrains:annotations:13.0@pom", - "org.jetbrains.kotlin:kotlin-stdlib:1.2.60@jar", - "org.jetbrains.kotlin:kotlin-stdlib:1.2.60@pom", - "org.jetbrains.kotlin:kotlin-stdlib-common:1.2.60@jar", - "org.jetbrains.kotlin:kotlin-stdlib-common:1.2.60@pom", - "org.sonatype.oss:oss-parent:7@pom" - ) - - all { - get("urls") { urls }.single().startsWith(BINTRAY_JCENTER_URL) - } - } - } - } - } - } - - test("builds single subproject") { - expectThat(build(subprojects = listOf(":child-a")).rootProject) { - get("root project dependencies") { projectDependencies }.and { - ids.containsExactly( - "junit:junit:4.12@jar", - "junit:junit:4.12@pom", - "org.hamcrest:hamcrest-core:1.3@jar", - "org.hamcrest:hamcrest-core:1.3@pom", - "org.hamcrest:hamcrest-parent:1.3@pom" - ) - - all { - get("urls") { urls }.single().startsWith(BINTRAY_JCENTER_URL) - } - } - - get("children") { children }.single().and { - get("name") { name }.isEqualTo("child-a") - get("projectDir") { projectDir }.isEqualTo("child-a") - - get("child-a project dependencies") { projectDependencies }.and { - ids.containsExactly( - "com.squareup.okio:okio:2.2.2@jar", - "com.squareup.okio:okio:2.2.2@pom", - "org.jetbrains:annotations:13.0@jar", - "org.jetbrains:annotations:13.0@pom", - "org.jetbrains.kotlin:kotlin-stdlib:1.2.60@jar", - "org.jetbrains.kotlin:kotlin-stdlib:1.2.60@pom", - "org.jetbrains.kotlin:kotlin-stdlib-common:1.2.60@jar", - "org.jetbrains.kotlin:kotlin-stdlib-common:1.2.60@pom" - ) - - all { - get("urls") { urls }.single().startsWith(BINTRAY_JCENTER_URL) - } - } - } - } - } - } - - withFixture("subprojects/dependent-subprojects") { - test("includes dependent subprojects") { - expectThat(build(subprojects = listOf(":child-a"))) { - get("children") { rootProject.children } - .map { it.path } - .containsExactlyInAnyOrder(":child-a", ":child-b", ":child-c") - } - - expectThat(build(subprojects = listOf(":child-b"))) { - get("children") { rootProject.children } - .map { it.path } - .containsExactlyInAnyOrder(":child-b", ":child-c") - } - } - } - } -} diff --git a/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/TestUtil.kt b/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/TestUtil.kt deleted file mode 100644 index 114658d..0000000 --- a/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/TestUtil.kt +++ /dev/null @@ -1,300 +0,0 @@ -package org.nixos.gradle2nix - -import com.adobe.testing.s3mock.S3MockApplication -import com.adobe.testing.s3mock.junit5.S3MockExtension -import com.adobe.testing.s3mock.testsupport.common.S3MockStarter -import com.squareup.moshi.Moshi -import dev.minutest.ContextBuilder -import dev.minutest.MinutestFixture -import dev.minutest.Node -import dev.minutest.TestContextBuilder -import dev.minutest.afterEach -import dev.minutest.beforeEach -import dev.minutest.experimental.SKIP -import dev.minutest.experimental.TransformingAnnotation -import dev.minutest.given -import dev.minutest.givenClosable -import dev.minutest.given_ -import io.javalin.Javalin -import io.javalin.http.staticfiles.Location -import okio.buffer -import okio.source -import org.gradle.internal.classpath.DefaultClassPath -import org.gradle.testkit.runner.GradleRunner -import org.gradle.testkit.runner.internal.PluginUnderTestMetadataReading -import org.gradle.util.GradleVersion -import org.junit.jupiter.api.Assumptions.assumeTrue -import strikt.api.Assertion -import strikt.assertions.map -import java.io.Closeable -import java.io.File -import java.io.StringWriter -import java.util.concurrent.atomic.AtomicBoolean - -private val moshi = Moshi.Builder().build() - -val fixtureRoot = File(System.getProperty("fixtures")) - -val gradleVersion = System.getProperty("compat.gradle.version") - ?.let(GradleVersion::version) - ?: GradleVersion.current() - -val GRADLE_4_5 = GradleVersion.version("4.5") - -fun GRADLE_MIN(version: String) = object : TransformingAnnotation() { - override fun transform(node: Node): Node = - if (gradleVersion < GradleVersion.version(version)) SKIP.transform(node) else node -} - -private fun File.initscript() = resolve("init.gradle").also { - it.writer().use { out -> - val classpath = DefaultClassPath.of(PluginUnderTestMetadataReading.readImplementationClasspath()) - .asFiles.joinToString { n -> "'$n'" } - out.append(""" - initscript { - dependencies { - classpath files($classpath) - } - } - - apply plugin: org.nixos.gradle2nix.Gradle2NixPlugin - - """.trimIndent()) - } -} - -fun File.buildKotlin( - script: String, - configurations: List = emptyList(), - subprojects: List = emptyList() -): DefaultBuild { - assumeTrue(gradleVersion >= GRADLE_4_5) - resolve("build.gradle.kts").writeText(script) - return build(configurations, subprojects) -} - -private fun File.build( - configurations: List, - subprojects: List, - extraArguments: List = emptyList() -): DefaultBuild { - val log = StringWriter() - - val result = GradleRunner.create() - .withGradleVersion(gradleVersion.version) - .withProjectDir(this) - .forwardStdOutput(log) - .forwardStdError(log) - .withArguments( - "nixModel", - "--init-script=${initscript()}", - "--stacktrace", - "-Porg.nixos.gradle2nix.configurations=${configurations.joinToString(",")}", - "-Porg.nixos.gradle2nix.subprojects=${subprojects.joinToString(",")}", - *(extraArguments.toTypedArray()) - ) - .runCatching { build() } - - result.onFailure { error -> - System.err.print(log) - throw error - } - - print(log) - - return resolve("build/nix/model.json").run { - println(readText()) - source().buffer().use { src -> - checkNotNull(moshi.adapter(DefaultBuild::class.java).fromJson(src)) - } - } -} - -val > Assertion.Builder.ids: Assertion.Builder> - get() = map { it.id.toString() } - -private fun File.parents() = generateSequence(parentFile) { it.parentFile } - -abstract class ArgumentsSupplier(private val parent: ArgumentsSupplier? = null) { - open val arguments: List = emptyList() - - val extraArguments: List get() = (parent?.extraArguments ?: emptyList()) + arguments -} - -@MinutestFixture -class RepositoryFixture( - private val server: Javalin, - parent: ArgumentsSupplier? = null -) : ArgumentsSupplier(parent), Closeable { - override fun close() { - server.stop() - } -} - -@MinutestFixture -class S3Fixture( - private val name: String, - parent: ArgumentsSupplier? = null -) : ArgumentsSupplier(parent), Closeable { - private val s3mock = S3Mock( - initialBuckets = listOf(name), - secureConnection = false - ) - - override val arguments: List get() = listOf( - "-Dorg.gradle.s3.endpoint=${s3mock.serviceEndpoint}", - "-Dorg.nixos.gradle2nix.s3test=true" - ) - - init { - s3mock.startServer() - - val s3root = fixtureRoot.resolve(name) - val s3client = s3mock.createS3Client() - require(s3root.exists() && s3root.isDirectory) { - "$name: S3 fixture not found: $s3root" - } - s3root.walkTopDown() - .filter { it.isFile } - .forEach { file -> - val key = file.toRelativeString(s3root) - s3client.putObject(name, key, file) - } - } - - override fun close() { - s3mock.stopServer() - } -} - -@MinutestFixture -class TestFixture( - val name: String, - val source: File, - parent: ArgumentsSupplier? = null -) : ArgumentsSupplier(parent), Closeable { - val dest: File - - init { - require(source.exists() && source.isDirectory) { - "$name: Test fixture not found: $source}" - } - dest = createTempDir(prefix = name, suffix = "") - } - - override fun close() { - dest.deleteRecursively() - } -} - -@MinutestFixture -data class ProjectFixture( - private val parent: TestFixture, - private val source: File -) : Closeable { - private val dest: File - - init { - require(source.exists() && source.isDirectory && parent.source in source.parents()) { - "${parent.name}: Test project not found: $source" - } - val rel = source.toRelativeString(parent.source) - dest = parent.dest.resolve(rel) - } - - fun copySource() { - source.copyRecursively(dest, true) - } - - fun build( - configurations: List = emptyList(), - subprojects: List = emptyList() - ) = dest.build(configurations, subprojects, parent.extraArguments) - - override fun close() { - dest.deleteRecursively() - } -} - -fun ContextBuilder<*>.withBucket( - name: String, - block: TestContextBuilder<*, S3Fixture>.() -> Unit -) = derivedContext("with s3 bucket: $name") { - given_ { parent -> - S3Fixture(name, parent as? ArgumentsSupplier) - } - - afterEach { it.close() } - - block() -} - -fun ContextBuilder<*>.withRepository( - name: String, - block: TestContextBuilder<*, RepositoryFixture>.() -> Unit -) = derivedContext("with repository: $name") { - given_ { parent -> - RepositoryFixture( - server = Javalin.create { config -> - config.addStaticFiles("${fixtureRoot}/repositories/$name", Location.EXTERNAL) - }.start(9999), - parent = parent as? ArgumentsSupplier - ) - } - - afterEach { it.close() } - - block() -} - -fun ContextBuilder<*>.withFixture( - name: String, - block: TestContextBuilder<*, ProjectFixture>.() -> Unit -) = derivedContext(name) { - - val projectRoot = fixtureRoot.resolve(name).also { - check(it.exists()) { "$name: project fixture not found: $it" } - } - - given_ { parent -> - TestFixture(name, projectRoot, parent as? ArgumentsSupplier) - } - - val testRoots = projectRoot.listFiles()!! - .filter { it.isDirectory } - .map { it.absoluteFile } - .toList() - - testRoots.forEach { testRoot -> - derivedContext(testRoot.name) { - given_ { parent -> ProjectFixture(parent, testRoot) } - beforeEach { copySource() } - afterEach { close() } - block() - } - } -} - -class S3Mock( - initialBuckets: List = emptyList(), - secureConnection: Boolean = true -) : S3MockStarter( - mapOf( - S3MockApplication.PROP_INITIAL_BUCKETS to initialBuckets.joinToString(","), - S3MockApplication.PROP_SECURE_CONNECTION to secureConnection - ) -) { - private val running = AtomicBoolean() - - fun startServer() { - if (running.compareAndSet(false, true)) { - start() - } - } - - fun stopServer() { - if (running.compareAndSet(true, false)) { - stop() - } - } -} \ No newline at end of file diff --git a/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/WrapperTest.kt b/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/WrapperTest.kt deleted file mode 100644 index ad4a552..0000000 --- a/plugin/src/compatTest/kotlin/org/nixos/gradle2nix/WrapperTest.kt +++ /dev/null @@ -1,27 +0,0 @@ -package org.nixos.gradle2nix - -import dev.minutest.Tests -import dev.minutest.given -import dev.minutest.junit.JUnit5Minutests -import dev.minutest.rootContext -import dev.minutest.test -import strikt.api.expectThat -import strikt.assertions.isEqualTo -import java.io.File - -class WrapperTest : JUnit5Minutests { - @Tests - fun tests() = rootContext("wrapper tests") { - given { createTempDir("gradle2nix") } - - test("resolves gradle wrapper version") { - expectThat(buildKotlin(""" - tasks.withType { - gradleVersion = "5.5.1" - } - """.trimIndent())) { - get("gradle version") { gradle.version }.isEqualTo("5.5.1") - } - } - } -} \ No newline at end of file diff --git a/plugin/src/main/java/org/nixos/gradle2nix/ApiHack.java b/plugin/src/main/java/org/nixos/gradle2nix/ApiHack.java deleted file mode 100644 index eb721d3..0000000 --- a/plugin/src/main/java/org/nixos/gradle2nix/ApiHack.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.nixos.gradle2nix; - -import org.gradle.api.artifacts.Dependency; -import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency; - -import javax.annotation.Nullable; - -/** - * Workarounds for APIs improperly marked with @NonNullApi. - */ -interface ApiHack { - static Dependency defaultExternalModuleDependency(String group, String name, @Nullable String version) { - return new DefaultExternalModuleDependency(group, name, version); - } -} diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/ConfigurationResolver.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/ConfigurationResolver.kt deleted file mode 100644 index 039f894..0000000 --- a/plugin/src/main/kotlin/org/nixos/gradle2nix/ConfigurationResolver.kt +++ /dev/null @@ -1,303 +0,0 @@ -package org.nixos.gradle2nix - -import org.apache.ivy.Ivy -import org.apache.ivy.core.settings.IvySettings -import org.apache.ivy.plugins.parser.m2.PomReader -import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorParser -import org.apache.ivy.plugins.repository.url.URLResource -import org.apache.ivy.plugins.resolver.ChainResolver -import org.gradle.api.Project -import org.gradle.api.artifacts.Configuration -import org.gradle.api.artifacts.ModuleIdentifier -import org.gradle.api.artifacts.ResolvedArtifact -import org.gradle.api.artifacts.component.ComponentArtifactIdentifier -import org.gradle.api.artifacts.component.ModuleComponentIdentifier -import org.gradle.api.artifacts.dsl.DependencyHandler -import org.gradle.api.artifacts.dsl.RepositoryHandler -import org.gradle.api.artifacts.query.ArtifactResolutionQuery -import org.gradle.api.artifacts.result.ResolvedArtifactResult -import org.gradle.api.internal.artifacts.repositories.ResolutionAwareRepository -import org.gradle.ivy.IvyDescriptorArtifact -import org.gradle.ivy.IvyModule -import org.gradle.kotlin.dsl.getArtifacts -import org.gradle.kotlin.dsl.withArtifacts -import org.gradle.maven.MavenModule -import org.gradle.maven.MavenPomArtifact -import org.gradle.util.GradleVersion - -enum class ConfigurationScope { - BUILDSCRIPT, - PLUGIN, - PROJECT, - SETTINGS -} - -internal class ConfigurationResolverFactory( - project: Project, - scope: ConfigurationScope, - repositories: List -) { - private val ivySettings = IvySettings().apply { - defaultInit() - // This doesn't appear to be used, but it's better to define it explicitly than to introduce - // impurities into artifact resolution. - setDefaultRepositoryCacheBasedir(project.buildDir.resolve("tmp/gradle2nix/_cache").absolutePath) - setDictatorResolver(ChainResolver().also { chain -> - chain.settings = this@apply - for (resolver in resolvers) chain.add(resolver) - }) - } - - private val resolvers = repositories - .filterNot { it.createResolver().isLocal } - .mapNotNull { it.repositoryResolver(project, scope, ivySettings) } - - fun create(dependencies: DependencyHandler): ConfigurationResolver = - ConfigurationResolver(ivySettings, resolvers, dependencies) -} - -internal class ConfigurationResolver( - ivySettings: IvySettings, - private val resolvers: List, - private val dependencies: DependencyHandler -) { - private val failed = mutableSetOf() - private val ivy = Ivy.newInstance(ivySettings) - - val unresolved: List = failed.toList() - - fun resolve(configuration: Configuration): List { - val resolved = configuration.resolvedConfiguration.lenientConfiguration - - failed.addAll(resolved.unresolvedModuleDependencies.map { - DefaultArtifactIdentifier( - group = it.selector.group, - name = it.selector.name, - version = it.selector.version ?: "", - type = "module" - ) - }) - - val topLevelMetadata = resolved.firstLevelModuleDependencies - .flatMap { resolveMetadata(it.moduleGroup, it.moduleName, it.moduleVersion) } - - val allArtifacts = resolved.artifacts - .filter { it.id.componentIdentifier is ModuleComponentIdentifier } - .flatMap(::resolve) - - return (topLevelMetadata + allArtifacts).filter { it.urls.isNotEmpty() } - } - - private fun resolve(resolvedArtifact: ResolvedArtifact): List { - val componentId = resolvedArtifact.id.componentIdentifier as ModuleComponentIdentifier - - val artifactId = DefaultArtifactIdentifier( - group = componentId.group, - name = componentId.module, - version = componentId.version, - type = resolvedArtifact.type, - extension = resolvedArtifact.extension, - classifier = resolvedArtifact.classifier - ) - - val sha256 = resolvedArtifact.computeHash() - val artifacts = resolvers.mapNotNull { it.resolve(artifactId, sha256) }.merge() - if (artifacts.isEmpty()) failed.add(artifactId) - return artifacts + componentId.run { resolveMetadata(group, module, version) } - } - - private fun resolveMetadata( - group: String, - name: String, - version: String - ): List { - return resolvePoms(group, name, version) + - resolveDescriptors(group, name, version) + - resolveGradleMetadata(group, name, version) - } - - private fun resolvePoms( - group: String, - name: String, - version: String - ): List { - return dependencies.createArtifactResolutionQuery() - .forModuleCompat(group, name, version) - .withArtifacts(MavenModule::class, MavenPomArtifact::class) - .execute() - .resolvedComponents - .flatMap { it.getArtifacts(MavenPomArtifact::class) } - .filterIsInstance() - .flatMap { it.withParentPoms() } - .flatMap { resolvedPom -> - val componentId = resolvedPom.id.componentIdentifier as ModuleComponentIdentifier - val artifactId = DefaultArtifactIdentifier( - group = componentId.group, - name = componentId.module, - version = componentId.version, - type = "pom" - ) - // Intentionally not computing hash from the cached result; see ResolvedArtifact.computeHash() below. - val artifacts = resolvers.mapNotNull { it.resolve(artifactId) }.merge() - if (artifacts.isEmpty()) failed.add(artifactId) - artifacts - } - } - - private fun resolveDescriptors( - group: String, - name: String, - version: String - ): List { - return dependencies.createArtifactResolutionQuery() - .forModuleCompat(group, name, version) - .withArtifacts(IvyModule::class, IvyDescriptorArtifact::class) - .execute() - .resolvedComponents - .flatMap { it.getArtifacts(IvyDescriptorArtifact::class) } - .filterIsInstance() - .flatMap { it.withParentDescriptors() } - .flatMap { resolvedDesc -> - val componentId = resolvedDesc.id.componentIdentifier as ModuleComponentIdentifier - val artifactId = DefaultArtifactIdentifier( - group = componentId.group, - name = componentId.module, - version = componentId.version, - type = "ivy", - extension = "xml" - ) - // Intentionally not computing hash from the cached result; see ResolvedArtifact.computeHash() below. - val artifacts = resolvers.mapNotNull { it.resolve(artifactId) }.merge() - if (artifacts.isEmpty()) failed.add(artifactId) - artifacts - } - } - - private fun resolveGradleMetadata( - group: String, - name: String, - version: String - ): List { - val artifactId = DefaultArtifactIdentifier( - group = group, - name = name, - version = version, - type = "module" - ) - val artifacts = resolvers.mapNotNull { it.resolve(artifactId) }.merge() - if (artifacts.isEmpty()) failed.add(artifactId) - return artifacts - } - - private fun ResolvedArtifactResult.parentPom(): ResolvedArtifactResult? { - val resource = URLResource(file.toURI().toURL()) - val reader = PomReader(resource.url, resource) - - return if (reader.hasParent()) { - dependencies.createArtifactResolutionQuery() - .forModuleCompat(reader.parentGroupId, reader.parentArtifactId, reader.parentVersion) - .withArtifacts(MavenModule::class, MavenPomArtifact::class) - .execute() - .resolvedComponents - .flatMap { it.getArtifacts(MavenPomArtifact::class) } - .filterIsInstance() - .firstOrNull() - } else { - null - } - } - - private fun ResolvedArtifactResult.withParentPoms(): List = - generateSequence(this) { it.parentPom() }.toList() - - private fun ResolvedArtifactResult.parentDescriptors(seen: Set): List { - val url = file.toURI().toURL() - val parser = XmlModuleDescriptorParser.getInstance() - - val descriptor = parser.parseDescriptor(ivy.settings, url, false) - - return descriptor.inheritedDescriptors.mapNotNull { desc -> - dependencies.createArtifactResolutionQuery() - .forModuleCompat( - desc.parentRevisionId.organisation, - desc.parentRevisionId.name, - desc.parentRevisionId.revision - ) - .withArtifacts(IvyModule::class, IvyDescriptorArtifact::class) - .execute() - .resolvedComponents - .flatMap { it.getArtifacts(IvyDescriptorArtifact::class) } - .filterIsInstance() - .firstOrNull() - }.filter { it.id !in seen } - } - - private fun ResolvedArtifactResult.withParentDescriptors(): List { - val seen = mutableSetOf() - return generateSequence(listOf(this)) { descs -> - val parents = descs.flatMap { it.parentDescriptors(seen) } - seen.addAll(parents.map(ResolvedArtifactResult::getId)) - parents.takeUnless { it.isEmpty() } - }.flatten().distinct().toList() - } -} - -private fun ArtifactResolutionQuery.forModuleCompat( - group: String, - name: String, - version: String -): ArtifactResolutionQuery { - return if (GradleVersion.current() >= GradleVersion.version("4.5")) { - forModule(group, name, version) - } else { - forComponents(ModuleComponentId(group, name, version)) - } -} - -private data class ModuleComponentId( - private val moduleId: ModuleId, - private val version: String -) : ModuleComponentIdentifier { - - constructor( - group: String, - name: String, - version: String - ) : this(ModuleId(group, name), version) - - override fun getGroup(): String = moduleId.group - override fun getModule(): String = moduleId.name - override fun getVersion(): String = version - override fun getModuleIdentifier(): ModuleIdentifier = moduleId - override fun getDisplayName(): String = - arrayOf(group, module, version).joinToString(":") -} - -private data class ModuleId( - private val group: String, - private val name: String -) : ModuleIdentifier { - override fun getGroup(): String = group - override fun getName(): String = name -} - -private fun List.merge(): List { - return groupingBy { it.id } - .reduce { _, dest, next -> dest.copy(urls = dest.urls + next.urls) } - .values.toList() -} - -private fun ResolvedArtifact.computeHash(): String? { - // Hack: Some POM files are served with CRLF line endings, e.g. javax.servlet:javax.servlet-api:3.1.0. - // Gradle stores these normalized with LF line endings, which will not match the eventual hash - // of the fixed-output derivation which produces the POM artifact. - // - // A similar issue can exist for Apache Ivy; see https://issues.apache.org/jira/browse/IVY-1156. - // - // Ignore these artifacts, and defer hash calculation to RepositoryResolver. - if (type == "pom" || type == "ivy") { - return null - } - - return file.sha256() -} \ No newline at end of file diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/Gradle2NixPlugin.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/Gradle2NixPlugin.kt index d0a0b3e..b5a0eac 100644 --- a/plugin/src/main/kotlin/org/nixos/gradle2nix/Gradle2NixPlugin.kt +++ b/plugin/src/main/kotlin/org/nixos/gradle2nix/Gradle2NixPlugin.kt @@ -1,282 +1,23 @@ +@file:Suppress("UnstableApiUsage") + package org.nixos.gradle2nix -import com.squareup.moshi.Moshi import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.artifacts.Configuration -import org.gradle.api.artifacts.ProjectDependency -import org.gradle.api.internal.GradleInternal -import org.gradle.api.internal.artifacts.repositories.ResolutionAwareRepository import org.gradle.api.invocation.Gradle -import org.gradle.api.tasks.TaskContainer -import org.gradle.api.tasks.wrapper.Wrapper -import org.gradle.kotlin.dsl.getByName -import org.gradle.kotlin.dsl.newInstance -import org.gradle.kotlin.dsl.support.serviceOf -import org.gradle.kotlin.dsl.withType -import org.gradle.plugin.management.PluginRequest -import org.gradle.tooling.provider.model.ToolingModelBuilder -import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry -import org.gradle.util.GradleVersion -import java.net.URL -import java.util.* +import org.nixos.gradle2nix.dependencygraph.AbstractDependencyExtractorPlugin @Suppress("unused") -open class Gradle2NixPlugin : Plugin { - override fun apply(gradle: Gradle): Unit = gradle.run { - val pluginRequests = collectPlugins() - - projectsLoaded { - val modelProperties = rootProject.loadModelProperties() - rootProject.serviceOf() - .register(NixToolingModelBuilder(modelProperties, pluginRequests)) - - rootProject.tasks.registerCompat("nixModel") { - doLast { - val outFile = project.mkdir(project.buildDir.resolve("nix")).resolve("model.json") - val model = project.buildModel(modelProperties, pluginRequests) - outFile.bufferedWriter().use { out -> - out.write( - Moshi.Builder().build() - .adapter(DefaultBuild::class.java) - .indent(" ") - .toJson(model) - ) - out.flush() - } - } - } +class Gradle2NixPlugin : Plugin { + override fun apply(gradle: Gradle) { + // Only apply the dependency extractor to the root build + if (gradle.parent == null) { + gradle.pluginManager.apply(NixDependencyExtractorPlugin::class.java) } - } -} - -private fun TaskContainer.registerCompat(name: String, configureAction: Task.() -> Unit) { - if (GradleVersion.current() >= GradleVersion.version("4.9")) { - register(name, configureAction) - } else { - create(name, configureAction) - } -} - -private class NixToolingModelBuilder( - private val modelProperties: ModelProperties, - private val pluginRequests: List -) : ToolingModelBuilder { - override fun canBuild(modelName: String): Boolean { - return modelName == NIX_MODEL_NAME + gradle.pluginManager.apply(ForceDependencyResolutionPlugin::class.java) } - override fun buildAll(modelName: String, project: Project): Build = - project.buildModel(modelProperties, pluginRequests) -} - -private fun Gradle.collectPlugins(): List { - val pluginRequests = mutableListOf() - gradle.settingsEvaluated { - pluginManagement.resolutionStrategy.eachPlugin { - if (requested.id.namespace != null && requested.id.namespace != "org.gradle") { - pluginRequests.add(target) - } - } - } - return pluginRequests -} - -private fun Project.buildModel( - modelProperties: ModelProperties, - pluginRequests: List -): DefaultBuild { - val settingsDependencies = settingsDependencies() - val plugins = buildPlugins(pluginRequests) - - val subprojects = if (modelProperties.subprojects.isEmpty()) { - project.subprojects - } else { - project.subprojects - .filter { it.path in modelProperties.subprojects } - // Include dependent subprojects as well - .flatMap { setOf(it) + it.dependentSubprojects(modelProperties.configurations) } - .toSet() - } - - return DefaultBuild( - gradle = buildGradle(), - settingsDependencies = settingsDependencies, - pluginDependencies = plugins, - rootProject = buildProject(modelProperties.configurations, subprojects, plugins), - includedBuilds = includedBuilds() - ) -} - -@Suppress("UnstableApiUsage") -private fun Project.buildGradle(): DefaultGradle = - with(tasks.getByName("wrapper")) { - DefaultGradle( - version = gradleVersion, - type = distributionType.name.toLowerCase(Locale.US), - url = distributionUrl, - sha256 = sha256, - nativeVersion = gradle.gradleHomeDir?.resolve("lib")?.listFiles() - ?.firstOrNull { f -> nativePlatformJarRegex matches f.name }?.let { nf -> - nativePlatformJarRegex.find(nf.name)?.groupValues?.get(1) - } - ?: throw IllegalStateException( - """ - Failed to find native-platform jar in ${gradle.gradleHomeDir}. - Ask Tad to fix this. - """.trimIndent() - ) - ) - } - -private fun Project.settingsDependencies(): List { - val buildscript = (gradle as GradleInternal).settings.buildscript - - val resolverFactory = ConfigurationResolverFactory( - this, - ConfigurationScope.SETTINGS, - buildscript.repositories.filterIsInstance() - ) - val resolver = resolverFactory.create(buildscript.dependencies) - - logger.lifecycle(" Settings script") - - val dependencies = buildscript.configurations - .flatMap(resolver::resolve) - .distinct() - .sorted() - - if (resolver.unresolved.isNotEmpty()) { - logger.warn(buildString { - append(" Failed to resolve settings script dependencies:\n") - for (id in resolver.unresolved) { - append(" - $id\n") - } - }) - } - - return dependencies -} - -private fun Project.buildPlugins(pluginRequests: List): List { - return objects.newInstance(this).resolve(pluginRequests).distinct().sorted() -} - -private fun Project.includedBuilds(): List = - gradle.includedBuilds.map { - DefaultIncludedBuild(it.name, it.projectDir.toRelativeString(project.projectDir)) - } - -private fun Project.buildProject( - explicitConfigurations: List, - explicitSubprojects: Collection, - pluginArtifacts: List -): DefaultProject { - logger.lifecycle(" Subproject: $path") - - val (buildscriptDependencies, buildscriptUnresolved) = buildscriptDependencies(pluginArtifacts) - - if (buildscriptUnresolved.isNotEmpty()) { - logger.warn(buildString { - append(" Failed to resolve buildscript dependencies:\n") - for (id in buildscriptUnresolved) { - append(" - $id\n") - } - }) - } - - val (projectDependencies, projectUnresolved) = projectDependencies(explicitConfigurations) - - if (projectUnresolved.isNotEmpty()) { - logger.warn(buildString { - append(" Failed to resolve project dependencies:\n") - for (id in projectUnresolved) { - append(" - $id\n") - } - }) - } - - return DefaultProject( - name = name, - version = version.toString(), - path = path, - projectDir = projectDir.toRelativeString(rootProject.projectDir), - buildscriptDependencies = buildscriptDependencies, - projectDependencies = projectDependencies, - children = explicitSubprojects.map { - it.buildProject(explicitConfigurations, emptyList(), pluginArtifacts) - } - ) -} - -private fun Project.buildscriptDependencies( - pluginArtifacts: List -): Pair, List> { - val resolverFactory = ConfigurationResolverFactory( - this, - ConfigurationScope.BUILDSCRIPT, - buildscript.repositories.filterIsInstance() - ) - val resolver = resolverFactory.create(buildscript.dependencies) - val pluginIds = pluginArtifacts.map(DefaultArtifact::id) - return buildscript.configurations - .flatMap(resolver::resolve) - .distinct() - .filter { it.id !in pluginIds } - .sorted() to resolver.unresolved -} - -private fun Project.projectDependencies( - explicitConfigurations: List -): Pair, List> { - val resolver = ConfigurationResolverFactory( - this, - ConfigurationScope.PROJECT, - RepositoriesCollector.create(project).collectRepositories() - ).create(dependencies) - return collectConfigurations(explicitConfigurations) - .flatMap(resolver::resolve) - .distinct() - .sorted() to resolver.unresolved -} - -private fun Project.dependentSubprojects(explicitConfigurations: List): Set { - return collectConfigurations(explicitConfigurations) - .flatMap { it.allDependencies.withType() } - .map { it.dependencyProject } - .toSet() - .flatMap { setOf(it) + it.dependentSubprojects(explicitConfigurations) } - .toSet() -} - -private fun Project.collectConfigurations( - explicitConfigurations: List -): Set { - return if (explicitConfigurations.isEmpty()) { - configurations.filter { it.isCanBeResolved }.toSet() - } else { - configurations.filter { it.name in explicitConfigurations }.toSet() + class NixDependencyExtractorPlugin : AbstractDependencyExtractorPlugin() { + override fun getRendererClassName(): String = + NixDependencyGraphRenderer::class.java.name } } - -private fun fetchDistSha256(url: String): String { - return URL("$url.sha256").openConnection().run { - connect() - getInputStream().reader().use { it.readText() } - } -} - -private val nativePlatformJarRegex = Regex("""native-platform-([\d.]+(-(alpha|beta|milestone)-\d+)?)\.jar""") - -private val Wrapper.sha256: String - get() { - return if (GradleVersion.current() < GradleVersion.version("4.5")) { - fetchDistSha256(distributionUrl) - } else { - @Suppress("UnstableApiUsage") - distributionSha256Sum ?: fetchDistSha256(distributionUrl) - } - } - -private const val NIX_MODEL_NAME = "org.nixos.gradle2nix.Build" diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/ModelProperties.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/ModelProperties.kt deleted file mode 100644 index 2d0fad2..0000000 --- a/plugin/src/main/kotlin/org/nixos/gradle2nix/ModelProperties.kt +++ /dev/null @@ -1,20 +0,0 @@ -package org.nixos.gradle2nix - -import org.gradle.api.Project - -data class ModelProperties( - val configurations: List, - val subprojects: List -) - -internal fun Project.loadModelProperties(): ModelProperties { - return ModelProperties( - configurations = this["org.nixos.gradle2nix.configurations"]?.split(",") ?: emptyList(), - subprojects = this["org.nixos.gradle2nix.subprojects"]?.split(",") ?: emptyList() - ) -} - -private operator fun Project.get(key: String): String? { - return System.getProperty(key)?.takeIf { it.isNotEmpty() } - ?: (properties[key] as? String)?.takeIf { it.isNotEmpty() } -} \ No newline at end of file diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/NixDependencyGraphRenderer.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/NixDependencyGraphRenderer.kt new file mode 100644 index 0000000..2f23bbd --- /dev/null +++ b/plugin/src/main/kotlin/org/nixos/gradle2nix/NixDependencyGraphRenderer.kt @@ -0,0 +1,21 @@ +package org.nixos.gradle2nix + +import java.io.File +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.encodeToStream +import org.nixos.gradle2nix.dependencygraph.DependencyGraphRenderer +import org.nixos.gradle2nix.dependencygraph.model.ResolvedConfiguration + +class NixDependencyGraphRenderer : DependencyGraphRenderer { + @OptIn(ExperimentalSerializationApi::class) + override fun outputDependencyGraph( + resolvedConfigurations: List, + outputDirectory: File + ) { + val graphOutputFile = File(outputDirectory, "dependency-graph.json") + graphOutputFile.outputStream().buffered().use { output -> + Json.encodeToStream(resolvedConfigurations, output) + } + } +} diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/PluginResolver.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/PluginResolver.kt deleted file mode 100644 index fc0d8e2..0000000 --- a/plugin/src/main/kotlin/org/nixos/gradle2nix/PluginResolver.kt +++ /dev/null @@ -1,31 +0,0 @@ -package org.nixos.gradle2nix - -import org.gradle.api.Project -import org.gradle.api.internal.artifacts.repositories.ResolutionAwareRepository -import org.gradle.plugin.management.PluginRequest -import org.gradle.plugin.use.internal.PluginDependencyResolutionServices -import javax.inject.Inject - -internal open class PluginResolver @Inject constructor( - project: Project, - pluginDependencyResolutionServices: PluginDependencyResolutionServices -) { - private val configurations = pluginDependencyResolutionServices.configurationContainer - - private val resolver = ConfigurationResolverFactory( - project, - ConfigurationScope.PLUGIN, - pluginDependencyResolutionServices.resolveRepositoryHandler.filterIsInstance() - ).create(pluginDependencyResolutionServices.dependencyHandler) - - fun resolve(pluginRequests: List): List { - val markerDependencies = pluginRequests.map { request -> - request.module?.let { module -> - ApiHack.defaultExternalModuleDependency(module.group, module.name, module.version) - } ?: request.id.id.let { id -> - ApiHack.defaultExternalModuleDependency(id, "$id.gradle.plugin", request.version) - } - } - return resolver.resolve(configurations.detachedConfiguration(*markerDependencies.toTypedArray())) - } -} diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/RepositoriesCollector.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/RepositoriesCollector.kt deleted file mode 100644 index 3b5dc4a..0000000 --- a/plugin/src/main/kotlin/org/nixos/gradle2nix/RepositoriesCollector.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.nixos.gradle2nix - -import org.gradle.api.internal.artifacts.repositories.ResolutionAwareRepository -import org.gradle.api.Project -import org.gradle.api.artifacts.dsl.RepositoryHandler -import org.gradle.api.initialization.dsl.ScriptHandler -import org.gradle.api.internal.artifacts.RepositoriesSupplier -import org.gradle.kotlin.dsl.newInstance -import org.gradle.util.GradleVersion -import javax.inject.Inject - -interface RepositoriesCollector { - fun collectRepositories(): List - - companion object { - fun create(project: Project): RepositoriesCollector = - if (GradleVersion.current() >= GradleVersion.version("6.8")) { - project.objects.newInstance() - } else { - project.objects.newInstance() - } - } -} - -open class RepositoriesCollectorBase @Inject constructor( - private val repositories: RepositoryHandler -): RepositoriesCollector { - override fun collectRepositories(): List = - repositories.filterIsInstance() -} - -open class RepositoriesCollector68 @Inject constructor( - private val repositoriesSupplier: RepositoriesSupplier -): RepositoriesCollector { - override fun collectRepositories(): List = - repositoriesSupplier.get() -} diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/RepositoryResolver.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/RepositoryResolver.kt deleted file mode 100644 index 33ce076..0000000 --- a/plugin/src/main/kotlin/org/nixos/gradle2nix/RepositoryResolver.kt +++ /dev/null @@ -1,317 +0,0 @@ -package org.nixos.gradle2nix - -import com.amazonaws.auth.BasicAWSCredentials -import com.amazonaws.auth.BasicSessionCredentials -import org.apache.ivy.core.LogOptions -import org.apache.ivy.core.cache.ArtifactOrigin -import org.apache.ivy.core.cache.CacheResourceOptions -import org.apache.ivy.core.cache.DefaultRepositoryCacheManager -import org.apache.ivy.core.cache.RepositoryCacheManager -import org.apache.ivy.core.module.id.ArtifactRevisionId -import org.apache.ivy.core.module.id.ModuleRevisionId -import org.apache.ivy.core.resolve.DownloadOptions -import org.apache.ivy.core.settings.IvySettings -import org.apache.ivy.core.settings.TimeoutConstraint -import org.apache.ivy.plugins.repository.Repository -import org.apache.ivy.plugins.repository.Resource -import org.apache.ivy.plugins.repository.url.URLRepository -import org.apache.ivy.plugins.repository.url.URLResource -import org.apache.ivy.plugins.resolver.AbstractResolver -import org.apache.ivy.plugins.resolver.IBiblioResolver -import org.apache.ivy.plugins.resolver.URLResolver -import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader -import org.codehaus.plexus.util.ReaderFactory -import org.codehaus.plexus.util.xml.pull.XmlPullParserException -import org.gradle.api.Project -import org.gradle.api.artifacts.repositories.ArtifactRepository -import org.gradle.api.artifacts.repositories.AuthenticationContainer -import org.gradle.api.artifacts.repositories.AuthenticationSupported -import org.gradle.api.artifacts.repositories.IvyArtifactRepository -import org.gradle.api.artifacts.repositories.MavenArtifactRepository -import org.gradle.api.artifacts.repositories.UrlArtifactRepository -import org.gradle.api.credentials.AwsCredentials -import org.gradle.api.internal.artifacts.repositories.ResolutionAwareRepository -import org.gradle.api.internal.artifacts.repositories.resolver.IvyResolver -import org.gradle.api.logging.Logger -import org.gradle.api.logging.Logging -import org.gradle.authentication.aws.AwsImAuthentication -import org.gradle.internal.authentication.AllSchemesAuthentication -import org.gradle.kotlin.dsl.getCredentials -import java.io.IOException -import java.net.URI -import org.apache.ivy.core.module.descriptor.Artifact as IvyArtifact -import org.apache.ivy.core.module.descriptor.DefaultArtifact as IvyDefaultArtifact -import org.apache.ivy.plugins.resolver.RepositoryResolver as IvyRepositoryResolver - -internal fun ResolutionAwareRepository.repositoryResolver( - project: Project, - scope: ConfigurationScope, - ivySettings: IvySettings -): RepositoryResolver? = - when(this) { - is MavenArtifactRepository -> MavenResolver(project, scope, ivySettings, this) - is IvyArtifactRepository -> IvyResolver(project, scope, ivySettings, this) - else -> null - } - -internal sealed class RepositoryResolver { - companion object { - @JvmStatic - protected val log: Logger = Logging.getLogger("gradle2nix") - } - - abstract val ivyResolver: IvyRepositoryResolver - - abstract fun resolve( - artifactId: DefaultArtifactIdentifier, - sha256: String? = null - ): DefaultArtifact? -} - -internal class MavenResolver( - project: Project, - scope: ConfigurationScope, - ivySettings: IvySettings, - repository: MavenArtifactRepository -) : RepositoryResolver() { - - override val ivyResolver: IBiblioResolver = IBiblioResolver().apply { - name = repository.name - root = repository.url.toString() - isM2compatible = true - settings = ivySettings - setCache(cacheManager(project, scope, ivySettings, repository).name) - setRepository(resolverRepository(repository)) - } - - override fun resolve(artifactId: DefaultArtifactIdentifier, sha256: String?): DefaultArtifact? { - val ivyArtifact: IvyArtifact = artifactId.toArtifact() - val origin = ivyResolver.locate(ivyArtifact) - if (origin == null || !origin.isExists) return null - val hash = if (sha256 != null) sha256 else { - val report = ivyResolver.download(origin, downloadOptions) - report.localFile?.sha256().also { - if (it == null) log.error(report.toString()) - } - } - if (hash == null) { - log.error("Failed to download '$artifactId' from repository '${ivyResolver.repository.name}'") - return null - } - val snapshotVersion: SnapshotVersion? = artifactId.version.snapshotVersion()?.let { - findSnapshotVersion(artifactId, it) - } - return DefaultArtifact( - id = artifactId, - name = artifactId.filename(snapshotVersion), - path = artifactId.repoPath(), - timestamp = snapshotVersion?.timestamp, - build = snapshotVersion?.build, - urls = listOf(origin.location), - sha256 = hash - ) - } - - private fun findSnapshotVersion( - artifactId: ArtifactIdentifier, - snapshotVersion: SnapshotVersion - ): SnapshotVersion { - if (snapshotVersion.timestamp != null) return snapshotVersion - val metadataLocation = "${ivyResolver.root}${artifactId.repoPath()}/maven-metadata.xml" - val metadataFile = ivyResolver.repositoryCacheManager.downloadRepositoryResource( - ivyResolver.repository.getResource(metadataLocation), - "maven-metadata", - "maven-metadata", - "xml", - CacheResourceOptions(), - ivyResolver.repository - ).localFile - - if (metadataFile == null) { - log.warn("maven-metadata.xml not found for snapshot dependency: $artifactId") - return snapshotVersion - } - - fun parseError(e: Throwable): Pair { - log.error("Failed to parse maven-metadata.xml for artifact: $artifactId") - log.error("Error was: ${e.message}", e) - return null to null - } - - val (timestamp: String?, build: Int?) = try { - MetadataXpp3Reader() - .read(ReaderFactory.newXmlReader(metadataFile)) - .versioning?.snapshot?.run { timestamp to buildNumber } - ?: null to null - } catch (e: IOException) { - parseError(e) - } catch (e: XmlPullParserException) { - parseError(e) - } - - return snapshotVersion.copy(timestamp = timestamp, build = build) - } -} - -internal class IvyResolver( - project: Project, - scope: ConfigurationScope, - ivySettings: IvySettings, - repository: IvyArtifactRepository -) : RepositoryResolver() { - - override val ivyResolver: URLResolver = URLResolver().apply { - name = repository.name - val ivyResolver = (repository as ResolutionAwareRepository).createResolver() as IvyResolver - isM2compatible = ivyResolver.isM2compatible - for (p in ivyResolver.ivyPatterns) addIvyPattern(p) - for (p in ivyResolver.artifactPatterns) addArtifactPattern(p) - settings = ivySettings - setCache(cacheManager(project, scope, ivySettings, repository).name) - setRepository(resolverRepository(repository)) - } - - override fun resolve(artifactId: DefaultArtifactIdentifier, sha256: String?): DefaultArtifact? { - val ivyArtifact: IvyArtifact = artifactId.toArtifact() - val origin = ivyResolver.locate(ivyArtifact)?.takeIf(ArtifactOrigin::isExists) ?: return null - val hash = if (sha256 != null) sha256 else { - val report = ivyResolver.download(origin, downloadOptions) - report.localFile?.sha256().also { - if (it == null) log.error(report.toString()) - } - } - if (hash == null) { - log.error("Failed to download '$artifactId' from repository '${ivyResolver.repository.name}'") - return null - } - return DefaultArtifact( - id = DefaultArtifactIdentifier(artifactId), - name = artifactId.filename(null), - path = artifactId.repoPath(), - urls = listOf(origin.location), - sha256 = hash - ) - } -} - -private fun cacheManager( - project: Project, - scope: ConfigurationScope, - ivySettings: IvySettings, - repository: ArtifactRepository -): RepositoryCacheManager { - return DefaultRepositoryCacheManager( - "${scope.name.toLowerCase()}-${repository.name}-cache", - ivySettings, - project.buildDir.resolve("tmp/gradle2nix/${repository.name}").also { - it.mkdirs() - } - ).also { - ivySettings.addRepositoryCacheManager(it) - } -} - -private val metadataTypes = setOf("pom", "ivy") - -private fun ArtifactIdentifier.toArtifact(): IvyArtifact { - val moduleRevisionId = ModuleRevisionId.newInstance(group, name, version) - val artifactRevisionId = ArtifactRevisionId.newInstance( - moduleRevisionId, - name, - type, - extension, - classifier?.let { mapOf("classifier" to it) } - ) - return IvyDefaultArtifact(artifactRevisionId, null, null, type in metadataTypes) -} - -private data class SnapshotVersion( - val base: String, - val timestamp: String?, - val build: Int? -) { - override fun toString(): String { - return if (timestamp != null && build != null) { - "$base-$timestamp-$build" - } else { - "$base-SNAPSHOT" - } - } -} - -private val SNAPSHOT_REGEX = Regex("^(.*)-SNAPSHOT$") -private val SNAPSHOT_TIMESTAMPED_REGEX = Regex("^(.*)-([0-9]{8}.[0-9]{6})-([0-9]+)$") - -private fun String.snapshotVersion(): SnapshotVersion? { - return SNAPSHOT_REGEX.find(this)?.destructured?.let { (base) -> - SnapshotVersion(base, null, null) - } ?: SNAPSHOT_TIMESTAMPED_REGEX.find(this)?.destructured?.let { (base, timestamp, build) -> - SnapshotVersion(base, timestamp, build.toInt()) - } -} - -private fun ArtifactIdentifier.repoPath(): String = - "${group.replace('.', '/')}/$name/$version" - -private fun ArtifactIdentifier.filename( - snapshotVersion: SnapshotVersion? -): String = buildString { - append(name, "-", snapshotVersion ?: version) - if (classifier != null) append("-", classifier) - append(".", extension) -} - -private val downloadOptions = DownloadOptions().apply { - log = LogOptions.LOG_DEFAULT -} - -private fun AbstractResolver.resolverRepository( - repository: T -) : Repository -where T : ArtifactRepository, - T : AuthenticationSupported = - when (val scheme = repository.url.scheme) { - "s3" -> s3Repository( - repository.getCredentials(AwsCredentials::class), - LazyTimeoutConstraint(this) - ) - "http", "https" -> URLRepository(LazyTimeoutConstraint(this)) - else -> throw IllegalStateException("Unknown repository URL scheme: $scheme") - } - -private fun s3Repository( - credentials: AwsCredentials?, - timeoutConstraint: TimeoutConstraint -): Repository { - val awsCredentials = credentials?.let { - if (it.sessionToken == null) { - BasicAWSCredentials(it.accessKey, it.secretKey) - } else { - BasicSessionCredentials(it.accessKey, it.secretKey, it.sessionToken) - } - } - return S3Repository( - credentials = awsCredentials, - endpoint = System.getProperty("org.gradle.s3.endpoint")?.let { URI(it) }, - timeoutConstraint = timeoutConstraint - ).apply { - name = "AWS S3" - } -} - -private class LazyTimeoutConstraint( - private val resolver: AbstractResolver -) : TimeoutConstraint { - override fun getConnectionTimeout(): Int = - resolver.timeoutConstraint?.connectionTimeout ?: -1 - - override fun getReadTimeout(): Int = - resolver.timeoutConstraint?.readTimeout ?: -1 -} - -// Compatibility shim as UrlArtifactRepository was added in Gradle 6.0 -private val ArtifactRepository.url: URI get() = when (this) { - is MavenArtifactRepository -> url - is IvyArtifactRepository -> url - else -> throw IllegalStateException("Unhandled repository type: ${this::class.simpleName}") -} \ No newline at end of file diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/Util.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/Util.kt deleted file mode 100644 index f7f8074..0000000 --- a/plugin/src/main/kotlin/org/nixos/gradle2nix/Util.kt +++ /dev/null @@ -1,24 +0,0 @@ -package org.nixos.gradle2nix - -import java.io.File -import java.net.URI -import java.net.URL -import java.security.MessageDigest - -private const val HEX = "0123456789abcdef" - -internal fun File.sha256(): String = readBytes().sha256() - -private fun ByteArray.sha256() = buildString { - MessageDigest.getInstance("SHA-256").digest(this@sha256) - .asSequence() - .map(Byte::toInt) - .forEach { - append(HEX[it shr 4 and 0x0f]) - append(HEX[it and 0x0f]) - } -} - -internal fun String.toUrl(): URL = URL(this) - -internal fun String.toUri(): URI = URI(this) diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/AbstractDependencyExtractorPlugin.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/AbstractDependencyExtractorPlugin.kt new file mode 100644 index 0000000..427b1e7 --- /dev/null +++ b/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/AbstractDependencyExtractorPlugin.kt @@ -0,0 +1,128 @@ +package org.nixos.gradle2nix.dependencygraph + +import org.gradle.api.Plugin +import org.gradle.api.invocation.Gradle +import org.gradle.api.provider.Provider +import org.gradle.internal.build.event.BuildEventListenerRegistryInternal +import org.gradle.util.GradleVersion +import org.nixos.gradle2nix.dependencygraph.extractor.DependencyExtractor +import org.nixos.gradle2nix.dependencygraph.extractor.DependencyExtractorBuildService +import org.nixos.gradle2nix.dependencygraph.extractor.LegacyDependencyExtractor +import org.nixos.gradle2nix.dependencygraph.util.service + +abstract class AbstractDependencyExtractorPlugin : Plugin { + // Register extension functions on `Gradle` type + private companion object : org.nixos.gradle2nix.dependencygraph.util.GradleExtensions() + + /** + * The name of an accessible class that implements `org.gradle.dependencygraph.DependencyGraphRenderer`. + */ + abstract fun getRendererClassName(): String + + internal lateinit var dependencyExtractorProvider: Provider + + override fun apply(gradle: Gradle) { + val gradleVersion = GradleVersion.current() + // Create the adapter based upon the version of Gradle + val applicatorStrategy = when { + gradleVersion < GradleVersion.version("8.0") -> PluginApplicatorStrategy.LegacyPluginApplicatorStrategy + else -> PluginApplicatorStrategy.DefaultPluginApplicatorStrategy + } + + // Create the service + dependencyExtractorProvider = applicatorStrategy.createExtractorService(gradle, getRendererClassName()) + + gradle.rootProject { project -> + dependencyExtractorProvider + .get() + .rootProjectBuildDirectory = project.buildDir + } + + // Register the service to listen for Build Events + applicatorStrategy.registerExtractorListener(gradle, dependencyExtractorProvider) + + // Register the shutdown hook that should execute at the completion of the Gradle build. + applicatorStrategy.registerExtractorServiceShutdown(gradle, dependencyExtractorProvider) + } + + /** + * Adapters for creating the [DependencyExtractor] and installing it into [Gradle] based upon the Gradle version. + */ + private interface PluginApplicatorStrategy { + + fun createExtractorService( + gradle: Gradle, + rendererClassName: String + ): Provider + + fun registerExtractorListener( + gradle: Gradle, + extractorServiceProvider: Provider + ) + + fun registerExtractorServiceShutdown( + gradle: Gradle, + extractorServiceProvider: Provider + ) + + @Suppress("DEPRECATION") + object LegacyPluginApplicatorStrategy : PluginApplicatorStrategy { + + override fun createExtractorService( + gradle: Gradle, + rendererClassName: String + ): Provider { + val dependencyExtractor = LegacyDependencyExtractor(rendererClassName) + return gradle.providerFactory.provider { dependencyExtractor } + } + + override fun registerExtractorListener( + gradle: Gradle, + extractorServiceProvider: Provider + ) { + gradle.buildOperationListenerManager + .addListener(extractorServiceProvider.get()) + } + + override fun registerExtractorServiceShutdown( + gradle: Gradle, + extractorServiceProvider: Provider + ) { + gradle.buildFinished { + extractorServiceProvider.get().close() + gradle.buildOperationListenerManager + .removeListener(extractorServiceProvider.get()) + } + } + } + + object DefaultPluginApplicatorStrategy : PluginApplicatorStrategy { + private const val SERVICE_NAME = "dependencyExtractorService" + + override fun createExtractorService( + gradle: Gradle, + rendererClassName: String + ): Provider { + return gradle.sharedServices.registerIfAbsent( + SERVICE_NAME, + DependencyExtractorBuildService::class.java + ) { it.parameters.rendererClassName.set(rendererClassName) } + } + + override fun registerExtractorListener( + gradle: Gradle, + extractorServiceProvider: Provider + ) { + gradle.service() + .onOperationCompletion(extractorServiceProvider) + } + + override fun registerExtractorServiceShutdown( + gradle: Gradle, + extractorServiceProvider: Provider + ) { + // No-op as DependencyExtractorService is Auto-Closable + } + } + } +} diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/DependencyGraphRenderer.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/DependencyGraphRenderer.kt new file mode 100644 index 0000000..9b786af --- /dev/null +++ b/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/DependencyGraphRenderer.kt @@ -0,0 +1,11 @@ +package org.nixos.gradle2nix.dependencygraph + +import java.io.File +import org.nixos.gradle2nix.dependencygraph.model.ResolvedConfiguration + +interface DependencyGraphRenderer { + fun outputDependencyGraph( + resolvedConfigurations: List, + outputDirectory: File + ) +} diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/extractor/DependencyExtractor.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/extractor/DependencyExtractor.kt new file mode 100644 index 0000000..c9010c4 --- /dev/null +++ b/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/extractor/DependencyExtractor.kt @@ -0,0 +1,342 @@ +package org.nixos.gradle2nix.dependencygraph.extractor + +import java.io.File +import java.net.URI +import java.util.Collections +import org.gradle.api.GradleException +import org.gradle.api.artifacts.result.ResolvedComponentResult +import org.gradle.api.artifacts.result.ResolvedDependencyResult +import org.gradle.api.internal.artifacts.DefaultProjectComponentIdentifier +import org.gradle.api.internal.artifacts.configurations.ResolveConfigurationDependenciesBuildOperationType +import org.gradle.api.logging.Logging +import org.gradle.internal.exceptions.DefaultMultiCauseException +import org.gradle.internal.operations.BuildOperationDescriptor +import org.gradle.internal.operations.BuildOperationListener +import org.gradle.internal.operations.OperationFinishEvent +import org.gradle.internal.operations.OperationIdentifier +import org.gradle.internal.operations.OperationProgressEvent +import org.gradle.internal.operations.OperationStartEvent +import org.nixos.gradle2nix.PARAM_INCLUDE_CONFIGURATIONS +import org.nixos.gradle2nix.PARAM_INCLUDE_PROJECTS +import org.nixos.gradle2nix.PARAM_REPORT_DIR +import org.nixos.gradle2nix.dependencygraph.DependencyGraphRenderer +import org.nixos.gradle2nix.dependencygraph.model.DependencyCoordinates +import org.nixos.gradle2nix.dependencygraph.model.DependencySource +import org.nixos.gradle2nix.dependencygraph.model.Repository +import org.nixos.gradle2nix.dependencygraph.model.ResolvedConfiguration +import org.nixos.gradle2nix.dependencygraph.model.ResolvedDependency +import org.nixos.gradle2nix.dependencygraph.util.loadOptionalParam + +abstract class DependencyExtractor : + BuildOperationListener, + AutoCloseable { + + private val resolvedConfigurations = Collections.synchronizedList(mutableListOf()) + + private val thrownExceptions = Collections.synchronizedList(mutableListOf()) + + var rootProjectBuildDirectory: File? = null + + // Properties are lazily initialized so that System Properties are initialized by the time + // the values are used. This is required due to a bug in older Gradle versions. (https://github.com/gradle/gradle/issues/6825) + private val configurationFilter by lazy { + ResolvedConfigurationFilter( + loadOptionalParam(PARAM_INCLUDE_PROJECTS), + loadOptionalParam(PARAM_INCLUDE_CONFIGURATIONS) + ) + } + + private val dependencyGraphReportDir by lazy { + loadOptionalParam(PARAM_REPORT_DIR) + } + + abstract fun getRendererClassName(): String + + override fun started(buildOperation: BuildOperationDescriptor, startEvent: OperationStartEvent) { + // This method will never be called when registered in a `BuildServiceRegistry` (ie. Gradle 6.1 & higher) + // No-op + } + + override fun progress(operationIdentifier: OperationIdentifier, progressEvent: OperationProgressEvent) { + // This method will never be called when registered in a `BuildServiceRegistry` (ie. Gradle 6.1 & higher) + // No-op + } + + override fun finished(buildOperation: BuildOperationDescriptor, finishEvent: OperationFinishEvent) { + handleBuildOperationType< + ResolveConfigurationDependenciesBuildOperationType.Details, + ResolveConfigurationDependenciesBuildOperationType.Result + >(buildOperation, finishEvent) { details, result -> extractConfigurationDependencies(details, result) } + } + + private inline fun handleBuildOperationType( + buildOperation: BuildOperationDescriptor, + finishEvent: OperationFinishEvent, + handler: (details: D, result: R) -> Unit + ) { + try { + handleBuildOperationTypeRaw(buildOperation, finishEvent, handler) + } catch (e: Throwable) { + thrownExceptions.add(e) + throw e + } + } + + private inline fun handleBuildOperationTypeRaw( + buildOperation: BuildOperationDescriptor, + finishEvent: OperationFinishEvent, + handler: (details: D, result: R) -> Unit + ) { + val details: D? = buildOperation.details.let { + if (it is D) it else null + } + val result: R? = finishEvent.result.let { + if (it is R) it else null + } + if (details == null && result == null) { + return + } else if (details == null || result == null) { + throw IllegalStateException("buildOperation.details & finishedEvent.result were unexpected types") + } + handler(details, result) + } + + private fun extractConfigurationDependencies( + details: ResolveConfigurationDependenciesBuildOperationType.Details, + result: ResolveConfigurationDependenciesBuildOperationType.Result + ) { + val repositories = details.repositories?.mapNotNull { + @Suppress("UNCHECKED_CAST") + Repository( + id = it.id, + type = enumValueOf(it.type), + name = it.name, + m2Compatible = it.type == "MAVEN" || (it.properties["M2_COMPATIBLE"] as? Boolean) ?: false, + metadataSources = (it.properties["METADATA_SOURCES"] as? List) ?: emptyList(), + metadataResources = metadataResources(it), + artifactResources = artifactResources(it), + ) + } ?: emptyList() + val rootComponent = result.rootComponent + + if (rootComponent.dependencies.isEmpty()) { + // No dependencies to extract: can safely ignore + return + } + val projectIdentityPath = (rootComponent.id as? DefaultProjectComponentIdentifier)?.identityPath?.path + + // TODO: At this point, any resolution not bound to a particular project will be assigned to the root "build :" + // This is because `details.buildPath` is always ':', which isn't correct in a composite build. + // It is possible to do better. By tracking the current build operation context, we can assign more precisely. + // See the Gradle Enterprise Build Scan Plugin: `ConfigurationResolutionCapturer_5_0` + val rootPath = projectIdentityPath ?: details.buildPath + + if (!configurationFilter.include(rootPath, details.configurationName)) { + LOGGER.debug("Ignoring resolved configuration: $rootPath - ${details.configurationName}") + return + } + + val rootId = if (projectIdentityPath == null) "build $rootPath" else componentId(rootComponent) + val rootSource = DependencySource(rootId, rootPath) + val resolvedConfiguration = ResolvedConfiguration(rootSource, details.configurationName, repositories) + + for (directDependency in getResolvedDependencies(rootComponent)) { + val directDep = createComponentNode( + componentId(directDependency), + rootSource, + true, + directDependency, + result.getRepositoryId(directDependency) + ) + resolvedConfiguration.addDependency(directDep) + + walkComponentDependencies(result, directDependency, directDep.source, resolvedConfiguration) + } + + resolvedConfigurations.add(resolvedConfiguration) + } + + private fun walkComponentDependencies( + result: ResolveConfigurationDependenciesBuildOperationType.Result, + component: ResolvedComponentResult, + parentSource: DependencySource, + resolvedConfiguration: ResolvedConfiguration + ) { + val componentSource = getSource(component, parentSource) + val direct = componentSource != parentSource + + val dependencyComponents = getResolvedDependencies(component) + for (dependencyComponent in dependencyComponents) { + val dependencyId = componentId(dependencyComponent) + if (!resolvedConfiguration.hasDependency(dependencyId)) { + val dependencyNode = createComponentNode( + dependencyId, + componentSource, + direct, + dependencyComponent, + result.getRepositoryId(component) + ) + resolvedConfiguration.addDependency(dependencyNode) + + walkComponentDependencies(result, dependencyComponent, componentSource, resolvedConfiguration) + } + } + } + + private fun getSource(component: ResolvedComponentResult, source: DependencySource): DependencySource { + val componentId = component.id + if (componentId is DefaultProjectComponentIdentifier) { + return DependencySource(componentId(component), componentId.identityPath.path) + } + return source + } + + private fun getResolvedDependencies(component: ResolvedComponentResult): List { + return component.dependencies.filterIsInstance().map { it.selected }.filter { it != component } + } + + private fun createComponentNode(componentId: String, source: DependencySource, direct: Boolean, component: ResolvedComponentResult, repositoryId: String?): ResolvedDependency { + val componentDependencies = component.dependencies.filterIsInstance().map { componentId(it.selected) } + return ResolvedDependency( + componentId, + source, + direct, + coordinates(component), + repositoryId, + componentDependencies + ) + } + + private fun componentId(component: ResolvedComponentResult): String { + return component.id.displayName + } + + private fun coordinates(component: ResolvedComponentResult): DependencyCoordinates { + // TODO: Consider and handle null moduleVersion + val moduleVersionIdentifier = component.moduleVersion!! + return DependencyCoordinates( + moduleVersionIdentifier.group, + moduleVersionIdentifier.name, + moduleVersionIdentifier.version + ) + } + + private fun writeDependencyGraph() { + val outputDirectory = getOutputDir() + outputDirectory.mkdirs() + createRenderer().outputDependencyGraph(resolvedConfigurations, outputDirectory) + LOGGER.info("Wrote dependency graph to ${getOutputDir()}") + } + + private fun createRenderer(): DependencyGraphRenderer { + LOGGER.info("Constructing renderer: ${getRendererClassName()}") + return Class.forName(getRendererClassName()).getDeclaredConstructor().newInstance() as DependencyGraphRenderer + } + + private fun getOutputDir(): File { + if (dependencyGraphReportDir != null) { + return File(dependencyGraphReportDir!!) + } + + if (rootProjectBuildDirectory == null) { + throw RuntimeException("Cannot determine report file location") + } + return File( + rootProjectBuildDirectory, + "reports/nix-dependency-graph" + ) + } + + override fun close() { + if (thrownExceptions.isNotEmpty()) { + throw DefaultMultiCauseException( + "The Gradle2Nix plugin encountered errors while extracting dependencies. " + + "Please report this issue at: https://github.com/tadfisher/gradle2nix/issues", + thrownExceptions + ) + } + try { + writeDependencyGraph() + } catch (e: RuntimeException) { + throw GradleException( + "The Gradle2Nix plugin encountered errors while writing the dependency snapshot json file. " + + "Please report this issue at: https://github.com/tadfisher/gradle2nix/issues", + e + ) + } + } + + companion object { + private val LOGGER = Logging.getLogger(DependencyExtractor::class.java) + + private const val M2_PATTERN = + "[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier])(.[ext])" + + private const val IVY_ARTIFACT_PATTERN = "[organisation]/[module]/[revision]/[type]s/[artifact](.[ext])"; + + private fun resources(urls: List, patterns: List): List { + if (urls.isEmpty()) { + return patterns + } + if (patterns.isEmpty()) { + return urls.map { it.toString() } + } + return mutableListOf().apply { + for (pattern in patterns) { + for (url in urls) { + add( + url.toString() + .removeSuffix("/") + .plus("/") + .plus(pattern.removePrefix("/")) + ) + } + } + } + } + + private fun metadataResources( + repository: ResolveConfigurationDependenciesBuildOperationType.Repository + ): List { + return when (repository.type) { + Repository.Type.MAVEN.name -> { + resources( + listOfNotNull(repository.properties["URL"] as? URI), + listOf(M2_PATTERN) + ) + } + Repository.Type.IVY.name -> { + @Suppress("UNCHECKED_CAST") + resources( + listOfNotNull(repository.properties["URL"] as? URI), + repository.properties["IVY_PATTERNS"] as? List ?: listOf(IVY_ARTIFACT_PATTERN) + ) + } + else -> emptyList() + } + } + + private fun artifactResources( + repository: ResolveConfigurationDependenciesBuildOperationType.Repository + ): List { + return when (repository.type) { + Repository.Type.MAVEN.name -> { + @Suppress("UNCHECKED_CAST") + resources( + listOfNotNull(repository.properties["URL"] as? URI) + .plus(repository.properties["ARTIFACT_URLS"] as? List ?: emptyList()), + listOf(M2_PATTERN) + ) + } + Repository.Type.IVY.name -> { + @Suppress("UNCHECKED_CAST") + resources( + listOfNotNull(repository.properties["URL"] as? URI), + repository.properties["ARTIFACT_PATTERNS"] as? List ?: listOf(IVY_ARTIFACT_PATTERN) + ) + } + else -> emptyList() + } + } + } +} diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/extractor/DependencyExtractorBuildService.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/extractor/DependencyExtractorBuildService.kt new file mode 100644 index 0000000..5f3c7bd --- /dev/null +++ b/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/extractor/DependencyExtractorBuildService.kt @@ -0,0 +1,19 @@ +package org.nixos.gradle2nix.dependencygraph.extractor + +import org.gradle.api.provider.Property +import org.gradle.api.services.BuildService +import org.gradle.api.services.BuildServiceParameters + +abstract class DependencyExtractorBuildService : + DependencyExtractor(), + BuildService +{ + // Some parameters for the web server + internal interface Params : BuildServiceParameters { + val rendererClassName: Property + } + + override fun getRendererClassName(): String { + return parameters.rendererClassName.get() + } +} diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/extractor/LegacyDependencyExtractor.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/extractor/LegacyDependencyExtractor.kt new file mode 100644 index 0000000..92dd5ea --- /dev/null +++ b/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/extractor/LegacyDependencyExtractor.kt @@ -0,0 +1,10 @@ +package org.nixos.gradle2nix.dependencygraph.extractor + +open class LegacyDependencyExtractor( + private val rendererClassName: String +) : DependencyExtractor() { + + override fun getRendererClassName(): String { + return rendererClassName + } +} diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/extractor/ResolvedConfigurationFilter.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/extractor/ResolvedConfigurationFilter.kt new file mode 100644 index 0000000..5cbd4af --- /dev/null +++ b/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/extractor/ResolvedConfigurationFilter.kt @@ -0,0 +1,16 @@ +package org.nixos.gradle2nix.dependencygraph.extractor + +class ResolvedConfigurationFilter(projectFilter: String?, configurationFilter: String?) { + val projectRegex = projectFilter?.toRegex() + val configurationRegex = configurationFilter?.toRegex() + + fun include(projectPath: String, configurationName: String): Boolean { + if (projectRegex != null && !projectRegex.matches(projectPath)) { + return false + } + if (configurationRegex != null && !configurationRegex.matches(configurationName)) { + return false + } + return true + } +} diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/util/GradleExtensions.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/util/GradleExtensions.kt new file mode 100644 index 0000000..b45d034 --- /dev/null +++ b/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/util/GradleExtensions.kt @@ -0,0 +1,19 @@ +package org.nixos.gradle2nix.dependencygraph.util + +import org.gradle.api.internal.GradleInternal +import org.gradle.api.invocation.Gradle +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.ProviderFactory +import org.gradle.internal.operations.BuildOperationListenerManager + +internal abstract class GradleExtensions { + + inline val Gradle.providerFactory: ProviderFactory + get() = service() + + inline val Gradle.buildOperationListenerManager: BuildOperationListenerManager + get() = service() +} + +internal inline fun Gradle.service(): T = + (this as GradleInternal).services.get(T::class.java) diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/util/PluginParameters.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/util/PluginParameters.kt new file mode 100644 index 0000000..a889f56 --- /dev/null +++ b/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/util/PluginParameters.kt @@ -0,0 +1,6 @@ +package org.nixos.gradle2nix.dependencygraph.util + +internal fun loadOptionalParam(envName: String): String? { + return System.getProperty(envName) + ?: System.getenv()[envName] +} diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/forceresolve/ForceDependencyResolutionPlugin.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/forceresolve/ForceDependencyResolutionPlugin.kt new file mode 100644 index 0000000..e5ade2e --- /dev/null +++ b/plugin/src/main/kotlin/org/nixos/gradle2nix/forceresolve/ForceDependencyResolutionPlugin.kt @@ -0,0 +1,65 @@ +package org.nixos.gradle2nix + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.invocation.Gradle +import org.gradle.api.tasks.TaskProvider +import org.gradle.util.GradleVersion +import org.nixos.gradle2nix.forceresolve.LegacyResolveProjectDependenciesTask +import org.nixos.gradle2nix.forceresolve.ResolveProjectDependenciesTask + +// TODO: Rename these + +/** + * Adds a task to resolve all dependencies in a Gradle build tree. + */ +class ForceDependencyResolutionPlugin : Plugin { + override fun apply(gradle: Gradle) { + gradle.projectsEvaluated { + val resolveAllDeps = gradle.rootProject.tasks.register(RESOLVE_ALL_TASK) + + // Depend on "dependencies" task in all projects + gradle.allprojects { project -> + val projectTaskFactory = getResolveProjectDependenciesTaskFactory() + val resolveProjectDeps = projectTaskFactory.create(project) + resolveAllDeps.configure { + it.dependsOn(resolveProjectDeps) + } + } + + // Depend on all 'resolveBuildDependencies' task in each included build + gradle.includedBuilds.forEach { includedBuild -> + resolveAllDeps.configure { + it.dependsOn(includedBuild.task(":$RESOLVE_ALL_TASK")) + } + } + } + } + + private fun getResolveProjectDependenciesTaskFactory(): ResolveProjectDependenciesTaskFactory { + val gradleVersion = GradleVersion.current() + val gradle8 = GradleVersion.version("8.0") + return if (gradleVersion >= gradle8) { + ResolveProjectDependenciesTaskFactory.Current + } else { + ResolveProjectDependenciesTaskFactory.Legacy + } + } + + private sealed interface ResolveProjectDependenciesTaskFactory { + fun create(project: Project): TaskProvider + + data object Current : ResolveProjectDependenciesTaskFactory { + override fun create(project: Project): TaskProvider { + return project.tasks.register(RESOLVE_PROJECT_TASK, ResolveProjectDependenciesTask::class.java) + } + } + + data object Legacy : ResolveProjectDependenciesTaskFactory { + override fun create(project: Project): TaskProvider { + return project.tasks.register(RESOLVE_PROJECT_TASK, LegacyResolveProjectDependenciesTask::class.java) + } + } + } +} diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/forceresolve/LegacyResolveProjectDependenciesTask.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/forceresolve/LegacyResolveProjectDependenciesTask.kt new file mode 100644 index 0000000..cae57d0 --- /dev/null +++ b/plugin/src/main/kotlin/org/nixos/gradle2nix/forceresolve/LegacyResolveProjectDependenciesTask.kt @@ -0,0 +1,20 @@ +package org.nixos.gradle2nix.forceresolve + +import org.gradle.api.DefaultTask +import org.gradle.api.artifacts.Configuration +import org.gradle.api.tasks.TaskAction +import org.gradle.work.DisableCachingByDefault + +@DisableCachingByDefault(because = "Not worth caching") +abstract class LegacyResolveProjectDependenciesTask: DefaultTask() { + private fun getReportableConfigurations(): List { + return project.configurations.filter { it.isCanBeResolved } + } + + @TaskAction + fun action() { + for (configuration in getReportableConfigurations()) { + configuration.incoming.resolutionResult.root + } + } +} diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/forceresolve/ResolveProjectDependenciesTask.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/forceresolve/ResolveProjectDependenciesTask.kt new file mode 100644 index 0000000..5747b21 --- /dev/null +++ b/plugin/src/main/kotlin/org/nixos/gradle2nix/forceresolve/ResolveProjectDependenciesTask.kt @@ -0,0 +1,31 @@ +package org.nixos.gradle2nix.forceresolve + +import org.gradle.api.DefaultTask +import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.result.ResolvedComponentResult +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.TaskAction +import org.gradle.internal.serialization.Cached +import org.gradle.work.DisableCachingByDefault + +@DisableCachingByDefault(because = "Not worth caching") +abstract class ResolveProjectDependenciesTask: DefaultTask() { + private val configurationResolvers = Cached.of { createConfigurationResolvers() } + + private fun createConfigurationResolvers(): List> { + return getReportableConfigurations().map { + it.incoming.resolutionResult.rootComponent + } + } + + private fun getReportableConfigurations(): List { + return project.configurations.filter { it.isCanBeResolved } + } + + @TaskAction + fun action() { + for (configuration in configurationResolvers.get()) { + configuration.get() + } + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 4376732..dd7323f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,44 +1,16 @@ @file:Suppress("UnstableApiUsage") -enableFeaturePreview("ONE_LOCKFILE_PER_PROJECT") - -pluginManagement { - val shadowVersion: String by settings - val stutterVersion: String by settings - - resolutionStrategy { - eachPlugin { - when (requested.id.id) { - "com.github.johnrengelman.shadow" -> useVersion(shadowVersion) - "org.ajoberstar.stutter" -> useVersion(stutterVersion) - } - when (requested.id.namespace) { - "org.jetbrains.kotlin", - "org.jetbrains.kotlin.plugin" -> useVersion(embeddedKotlinVersion) - } - } - } -} - -plugins { - kotlin("jvm") apply false - kotlin("kapt") apply false - id("com.github.johnrengelman.shadow") apply false - id("org.ajoberstar.stutter") apply false -} - dependencyResolutionManagement { repositories { - jcenter() + mavenCentral() + gradlePluginPortal() maven { url = uri("https://repo.gradle.org/gradle/libs-releases") } } - repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS) + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) } -buildscript { - configurations.classpath { - resolutionStrategy.activateDependencyLocking() - } -} - -include(":app", ":ivy", ":model", ":plugin") +include( + ":app", + ":model", + ":plugin", +)