Miscellaneous cleanup

This commit is contained in:
Tad Fisher
2024-05-29 17:47:31 -07:00
parent d13b7b0d6d
commit 301c64fa2f
46 changed files with 1512 additions and 1441 deletions

19
.editorconfig Normal file
View File

@@ -0,0 +1,19 @@
[*.{kt,kts}]
end_of_line = lf
ij_kotlin_allow_trailing_comma = true
ij_kotlin_allow_trailing_comma_on_call_site = true
ij_kotlin_imports_layout = *,java.**,javax.**,kotlin.**,^
ij_kotlin_line_break_after_multiline_when_entry = true
ij_kotlin_packages_to_use_import_on_demand = unset
indent_size = 4
indent_style = space
insert_final_newline = true
ktlint_argument_list_wrapping_ignore_when_parameter_count_greater_or_equal_than = unset
ktlint_chain_method_rule_force_multiline_when_chain_operator_count_greater_or_equal_than = unset
ktlint_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than = 1
ktlint_code_style = ktlint_official
ktlint_function_naming_ignore_when_annotated_with = [unset]
ktlint_function_signature_body_expression_wrapping = multiline
ktlint_function_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than = 2
ktlint_ignore_back_ticked_identifier = false
max_line_length = 140

View File

@@ -4,6 +4,19 @@
Generate [[https://nixos.org/nix/][Nix]] expressions which build [[https://gradle.org/][Gradle]]-based projects. Generate [[https://nixos.org/nix/][Nix]] expressions which build [[https://gradle.org/][Gradle]]-based projects.
** Table of contents
#+BEGIN_QUOTE
- [[#why][Why?]]
- [[#installation][Installation]]
- [[#flake][Flake]]
- [[#usage][Usage]]
- [[#for-packagers][For packagers]]
- [[#specifying-the-gradle-installation][Specifying the Gradle installation]]
- [[#contributing][Contributing]]
- [[#license][License]]
#+END_QUOTE
** Why? ** Why?
Nix is an OS-agnostic package manager, a language-agnostic build Nix is an OS-agnostic package manager, a language-agnostic build
@@ -80,7 +93,25 @@ nix-env -if "https://github.com/tadfisher/gradle2nix/archive/master.tar.gz"
=gradle2nix= is not yet packaged in =nixpkgs= itself, but work is =gradle2nix= is not yet packaged in =nixpkgs= itself, but work is
[[https://github.com/NixOS/nixpkgs/pull/77422][in progress]]. [[https://github.com/NixOS/nixpkgs/pull/77422][in progress]].
*** Flake (experimental) The [[./gradle.nix][buildGradlePackage]] function is provided via the
=gradle2nix.passthru.buildGradlePackage= attribute.
#+begin_src nix
{ pkgs ? import <nixpkgs> {} }:
let
gradle2nix = import (fetchTarball "https://github.com/tadfisher/gradle2nix/archive/master.tar.gz") {}
in
gradle2nix.buildGradlePackage {
pname = "my-package";
version = "1.0";
lockFile = ./gradle.lock;
gradleFlags = [ "installDist" ];
# ...
}
#+end_src
*** Flake
A [[./flake.nix][flake.nix]] is provided for those using [[https://nixos.wiki/wiki/Flakes][Nix flakes]]. For example, the A [[./flake.nix][flake.nix]] is provided for those using [[https://nixos.wiki/wiki/Flakes][Nix flakes]]. For example, the
following will build and run =gradle2nix= with the arguments provided following will build and run =gradle2nix= with the arguments provided
@@ -90,6 +121,26 @@ after =--=:
nix run github:tadfisher/gradle2nix -- --help nix run github:tadfisher/gradle2nix -- --help
#+end_example #+end_example
The [[./gradle.nix][buildGradlePackage]] function is provided via the
=builders= output.
#+begin_src nix
{
inputs.gradle2nix.url = "github:tadfisher/gradle2nix";
outputs = { self, gradle2nix }: {
packages.x86_64-linux.default = gradle2nix.builders.x86_64-linux.buildGradlePackage {
pname = "my-package";
version = "1.0";
lockFile = ./gradle.lock;
gradleFlags = [ "installDist" ];
# ...
};
};
}
#+end_src
** Usage ** Usage
#+begin_example #+begin_example
@@ -100,7 +151,7 @@ Gradle installation:
Where to find Gradle. By default, use the project's wrapper. Where to find Gradle. By default, use the project's wrapper.
--gradle-dist=<uri> Gradle distribution URI --gradle-dist=<uri> Gradle distribution URI
--gradle-home=<dir> Gradle home path (e.g. `nix eval nixpkgs#gradle.outPath`/lib/gradle) --gradle-home=<dir> Gradle home path (e.g. `nix eval --raw nixpkgs#gradle.outPath`/lib/gradle)
--gradle-wrapper=<value> Gradle wrapper version --gradle-wrapper=<value> Gradle wrapper version
Options: Options:
@@ -108,9 +159,8 @@ Options:
-p, --project=<path> Path to the project root (default: Current directory) -p, --project=<path> Path to the project root (default: Current directory)
-o, --out-dir=<dir> Path to write generated files (default: <project>) -o, --out-dir=<dir> Path to write generated files (default: <project>)
-l, --lock-file=<filename> Name of the generated lock file (default: gradle.lock) -l, --lock-file=<filename> Name of the generated lock file (default: gradle.lock)
-n, --nix-file=<filename> Name of the generated Nix file (default: gradle.nix) -j, --gradle-jdk=<dir> JDK home to use for launching Gradle (e.g. `nix eval --raw nixpkgs#openjdk.home`)
-j, --gradle-jdk=<dir> JDK home to use for launching Gradle (e.g. nix eval nixpkgs#openjdk.home) --log=(debug|info|warn|error) Print messages with this priority or higher (default: info)
--log=(debug|info|warn|error) Print messages with this priority or higher (default: error)
--dump-events Dump Gradle event logs to the output directory --dump-events Dump Gradle event logs to the output directory
--stacktrace Print a stack trace on error --stacktrace Print a stack trace on error
-h, --help Show this message and exit -h, --help Show this message and exit
@@ -169,8 +219,8 @@ Bug reports and feature requests are encouraged.
Code contributions are also encouraged. Please review the test cases Code contributions are also encouraged. Please review the test cases
in the [[./fixtures][fixtures]] directory and create a new one to reproduce any fixes in the [[./fixtures][fixtures]] directory and create a new one to reproduce any fixes
or test new features. See the [[./plugin/src/compatTest/kotlin/org/nixos/gradle2nix][existing compatibility tests]] for or test new features. See the [[./app/src/test/kotlin/org/nixos/gradle2nix/GoldenTest.kt][existing tests]]
examples of testing with these fixtures. for examples of testing with these fixtures.
** License ** License

View File

@@ -11,10 +11,8 @@ dependencies {
implementation(libs.clikt) implementation(libs.clikt)
implementation(libs.gradle.toolingApi) implementation(libs.gradle.toolingApi)
implementation(libs.kotlinx.coroutines.core) implementation(libs.kotlinx.coroutines.core)
implementation(libs.okio)
implementation(libs.serialization.json) implementation(libs.serialization.json)
runtimeOnly(libs.slf4j.simple) runtimeOnly(libs.slf4j.simple)
implementation(libs.xmlutil)
"share"(project(":plugin", configuration = "shadow")) { "share"(project(":plugin", configuration = "shadow")) {
isTransitive = false isTransitive = false
@@ -29,12 +27,13 @@ dependencies {
application { application {
mainClass.set("org.nixos.gradle2nix.MainKt") mainClass.set("org.nixos.gradle2nix.MainKt")
applicationName = "gradle2nix" applicationName = "gradle2nix"
applicationDefaultJvmArgs = listOf( applicationDefaultJvmArgs =
listOf(
"-Dorg.nixos.gradle2nix.share=@APP_HOME@/share", "-Dorg.nixos.gradle2nix.share=@APP_HOME@/share",
"-Dslf4j.internal.verbosity=ERROR" "-Dslf4j.internal.verbosity=ERROR",
) )
applicationDistribution applicationDistribution
.from(configurations.named("share"), files("../gradle.nix")) .from(configurations.named("share"))
.into("share") .into("share")
.rename("plugin.*\\.jar", "plugin.jar") .rename("plugin.*\\.jar", "plugin.jar")
} }
@@ -51,32 +50,31 @@ val updateGolden = providers.gradleProperty("update-golden")
tasks { tasks {
(run) { (run) {
dependsOn(installDist) enabled = false
doFirst {
systemProperties("org.nixos.gradle2nix.share" to installDist.get().destinationDir.resolve("share"))
}
} }
startScripts { startScripts {
doLast { doLast {
unixScript.writeText( unixScript.writeText(
unixScript.readText().replace("@APP_HOME@", "'\$APP_HOME'") unixScript.readText().replace("@APP_HOME@", "'\$APP_HOME'"),
) )
windowsScript.writeText( windowsScript.writeText(
windowsScript.readText().replace("@APP_HOME@", "%APP_HOME%")) windowsScript.readText().replace("@APP_HOME@", "%APP_HOME%"),
)
} }
} }
withType<Test> { // TODO Find out why this fails the configuration cache
notCompatibleWithConfigurationCache("huh?") test {
dependsOn(installDist) notCompatibleWithConfigurationCache("contains a Task reference")
val shareDir = layout.dir(installDist.map { it.destinationDir.resolve("share") })
doFirst { doFirst {
if (updateGolden.isPresent) { if (updateGolden.isPresent) {
systemProperty("org.nixos.gradle2nix.update-golden", "") systemProperty("org.nixos.gradle2nix.update-golden", "")
} }
systemProperties( systemProperties(
"org.nixos.gradle2nix.share" to installDist.get().destinationDir.resolve("share"), "org.nixos.gradle2nix.share" to shareDir.get().asFile,
"org.nixos.gradle2nix.m2" to "http://0.0.0.0:8989/m2" "org.nixos.gradle2nix.m2" to "http://0.0.0.0:8989/m2",
) )
} }
useJUnitPlatform() useJUnitPlatform()

View File

@@ -1,9 +1,5 @@
package org.nixos.gradle2nix package org.nixos.gradle2nix
import java.io.File
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.io.path.absolutePathString
import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.suspendCancellableCoroutine
import org.gradle.tooling.GradleConnectionException import org.gradle.tooling.GradleConnectionException
import org.gradle.tooling.GradleConnector import org.gradle.tooling.GradleConnector
@@ -12,8 +8,15 @@ import org.gradle.tooling.ResultHandler
import org.gradle.tooling.model.gradle.GradleBuild import org.gradle.tooling.model.gradle.GradleBuild
import org.nixos.gradle2nix.model.DependencySet import org.nixos.gradle2nix.model.DependencySet
import org.nixos.gradle2nix.model.RESOLVE_ALL_TASK import org.nixos.gradle2nix.model.RESOLVE_ALL_TASK
import java.io.File
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.io.path.absolutePathString
fun connect(config: Config, projectDir: File = config.projectDir): ProjectConnection = fun connect(
config: Config,
projectDir: File = config.projectDir,
): ProjectConnection =
GradleConnector.newConnector() GradleConnector.newConnector()
.apply { .apply {
when (val source = config.gradleSource) { when (val source = config.gradleSource) {
@@ -26,14 +29,16 @@ fun connect(config: Config, projectDir: File = config.projectDir): ProjectConnec
.forProjectDirectory(projectDir) .forProjectDirectory(projectDir)
.connect() .connect()
suspend fun ProjectConnection.buildModel(): GradleBuild = suspendCancellableCoroutine { continuation -> suspend fun ProjectConnection.buildModel(): GradleBuild =
suspendCancellableCoroutine { continuation ->
val cancellationTokenSource = GradleConnector.newCancellationTokenSource() val cancellationTokenSource = GradleConnector.newCancellationTokenSource()
continuation.invokeOnCancellation { cancellationTokenSource.cancel() } continuation.invokeOnCancellation { cancellationTokenSource.cancel() }
action { controller -> controller.buildModel } action { controller -> controller.buildModel }
.withCancellationToken(cancellationTokenSource.token()) .withCancellationToken(cancellationTokenSource.token())
.run(object : ResultHandler<GradleBuild> { .run(
object : ResultHandler<GradleBuild> {
override fun onComplete(result: GradleBuild) { override fun onComplete(result: GradleBuild) {
continuation.resume(result) continuation.resume(result)
} }
@@ -41,10 +46,12 @@ suspend fun ProjectConnection.buildModel(): GradleBuild = suspendCancellableCoro
override fun onFailure(failure: GradleConnectionException) { override fun onFailure(failure: GradleConnectionException) {
continuation.resumeWithException(failure) continuation.resumeWithException(failure)
} }
}) },
} )
}
suspend fun ProjectConnection.build(config: Config): DependencySet = suspendCancellableCoroutine { continuation -> suspend fun ProjectConnection.build(config: Config): DependencySet =
suspendCancellableCoroutine { continuation ->
val cancellationTokenSource = GradleConnector.newCancellationTokenSource() val cancellationTokenSource = GradleConnector.newCancellationTokenSource()
continuation.invokeOnCancellation { cancellationTokenSource.cancel() } continuation.invokeOnCancellation { cancellationTokenSource.cancel() }
@@ -61,7 +68,6 @@ suspend fun ProjectConnection.build(config: Config): DependencySet = suspendCanc
.setJavaHome(config.gradleJdk) .setJavaHome(config.gradleJdk)
.addArguments(config.gradleArgs) .addArguments(config.gradleArgs)
.addArguments( .addArguments(
"--no-parallel",
"--refresh-dependencies", "--refresh-dependencies",
"--gradle-user-home=${config.gradleHome}", "--gradle-user-home=${config.gradleHome}",
"--init-script=${config.appHome}/init.gradle", "--init-script=${config.appHome}/init.gradle",
@@ -70,7 +76,7 @@ suspend fun ProjectConnection.build(config: Config): DependencySet = suspendCanc
if (config.logger.stacktrace) { if (config.logger.stacktrace) {
addArguments("--stacktrace") addArguments("--stacktrace")
} }
if (config.logger.logLevel < LogLevel.error) { if (config.logger.logLevel < LogLevel.ERROR) {
setStandardOutput(System.err) setStandardOutput(System.err)
setStandardError(System.err) setStandardError(System.err)
} }
@@ -78,12 +84,13 @@ suspend fun ProjectConnection.build(config: Config): DependencySet = suspendCanc
withSystemProperties( withSystemProperties(
mapOf( mapOf(
"org.gradle.internal.operations.trace" to "org.gradle.internal.operations.trace" to
config.outDir.toPath().resolve("debug").absolutePathString() config.outDir.toPath().resolve("debug").absolutePathString(),
) ),
) )
} }
} }
.run(object : ResultHandler<DependencySet> { .run(
object : ResultHandler<DependencySet> {
override fun onComplete(result: DependencySet) { override fun onComplete(result: DependencySet) {
continuation.resume(result) continuation.resume(result)
} }
@@ -91,5 +98,6 @@ suspend fun ProjectConnection.build(config: Config): DependencySet = suspendCanc
override fun onFailure(failure: GradleConnectionException) { override fun onFailure(failure: GradleConnectionException) {
continuation.resumeWithException(failure) continuation.resumeWithException(failure)
} }
}) },
} )
}

View File

@@ -5,32 +5,43 @@ import kotlin.system.exitProcess
class Logger( class Logger(
val out: PrintStream = System.err, val out: PrintStream = System.err,
val logLevel: LogLevel = LogLevel.warn, val logLevel: LogLevel = LogLevel.WARN,
val stacktrace: Boolean = false, val stacktrace: Boolean = false,
) { ) {
fun debug(
fun debug(message: String, error: Throwable? = null) { message: String,
if (logLevel <= LogLevel.debug) { error: Throwable? = null,
) {
if (logLevel <= LogLevel.DEBUG) {
out.println("[DEBUG] $message") out.println("[DEBUG] $message")
printError(error) printError(error)
} }
} }
fun info(message: String, error: Throwable? = null) { fun info(
if (logLevel <= LogLevel.info) { message: String,
error: Throwable? = null,
) {
if (logLevel <= LogLevel.INFO) {
out.println("[INFO] $message") out.println("[INFO] $message")
printError(error) printError(error)
} }
} }
fun warn(message: String, error: Throwable? = null) { fun warn(
if (logLevel <= LogLevel.warn) { message: String,
error: Throwable? = null,
) {
if (logLevel <= LogLevel.WARN) {
out.println("[WARN] $message") out.println("[WARN] $message")
printError(error) printError(error)
} }
} }
fun error(message: String, error: Throwable? = null): Nothing { fun error(
message: String,
error: Throwable? = null,
): Nothing {
out.println("[ERROR] $message") out.println("[ERROR] $message")
printError(error) printError(error)
exitProcess(1) exitProcess(1)
@@ -43,6 +54,8 @@ class Logger(
} }
operator fun component1() = ::info operator fun component1() = ::info
operator fun component2() = ::warn operator fun component2() = ::warn
operator fun component3() = ::error operator fun component3() = ::error
} }

View File

@@ -14,19 +14,16 @@ import com.github.ajalt.clikt.parameters.options.defaultLazy
import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.flag
import com.github.ajalt.clikt.parameters.options.multiple import com.github.ajalt.clikt.parameters.options.multiple
import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.clikt.parameters.options.optionalValue
import com.github.ajalt.clikt.parameters.options.validate
import com.github.ajalt.clikt.parameters.types.enum import com.github.ajalt.clikt.parameters.types.enum
import com.github.ajalt.clikt.parameters.types.file import com.github.ajalt.clikt.parameters.types.file
import java.io.File
import java.net.URI
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.encodeToStream import kotlinx.serialization.json.encodeToStream
import org.gradle.internal.service.scopes.Scopes.Gradle
import org.gradle.tooling.model.gradle.GradleBuild import org.gradle.tooling.model.gradle.GradleBuild
import org.nixos.gradle2nix.model.DependencySet import org.nixos.gradle2nix.model.DependencySet
import java.io.File
import java.net.URI
data class Config( data class Config(
val appHome: File, val appHome: File,
@@ -38,100 +35,106 @@ data class Config(
val projectDir: File, val projectDir: File,
val tasks: List<String>, val tasks: List<String>,
val logger: Logger, val logger: Logger,
val dumpEvents: Boolean val dumpEvents: Boolean,
) )
@OptIn(ExperimentalSerializationApi::class) @OptIn(ExperimentalSerializationApi::class)
val JsonFormat = Json { val JsonFormat =
Json {
ignoreUnknownKeys = true ignoreUnknownKeys = true
prettyPrint = true prettyPrint = true
prettyPrintIndent = " " prettyPrintIndent = " "
} }
sealed interface GradleSource { sealed interface GradleSource {
data class Distribution(val uri: URI) : GradleSource data class Distribution(val uri: URI) : GradleSource
data class Path(val path: File) : GradleSource data class Path(val path: File) : GradleSource
data object Project : GradleSource data object Project : GradleSource
data class Wrapper(val version: String) : GradleSource data class Wrapper(val version: String) : GradleSource
} }
enum class LogLevel { enum class LogLevel {
debug, DEBUG,
info, INFO,
warn, WARN,
error, ERROR,
} }
class Gradle2Nix : CliktCommand( class Gradle2Nix : CliktCommand(
name = "gradle2nix", name = "gradle2nix",
) { ) {
private val tasks: List<String> by option( private val tasks: List<String> by option(
"--task", "-t", "--task",
"-t",
metavar = "TASK", metavar = "TASK",
help = "Gradle tasks to run" help = "Gradle tasks to run",
).multiple() ).multiple()
private val projectDir: File by option( private val projectDir: File by option(
"--project", "-p", "--project",
help = "Path to the project root") "-p",
.file() help = "Path to the project root",
.default(File("."), "Current directory") ).file(
.validate { file -> mustExist = true,
if (!file.exists()) fail("Directory \"$file\" does not exist.") mustBeReadable = true,
if (file.isFile) fail("Directory \"$file\" is a file.") canBeFile = false,
if (!file.canRead()) fail("Directory \"$file\" is not readable.") ).convert { file ->
if (!file.isProjectRoot()) fail("Directory \"$file\" is not a Gradle project.") getProjectRoot(file) ?: fail("Could not locate project root in \"$file\" or its parents.")
}.defaultLazy("Current directory") {
File(".")
} }
private val outDir: File? by option( private val outDir: File? by option(
"--out-dir", "-o", "--out-dir",
"-o",
metavar = "DIR", metavar = "DIR",
help = "Path to write generated files") help = "Path to write generated files",
)
.file(canBeFile = false, canBeDir = true) .file(canBeFile = false, canBeDir = true)
.defaultLazy("<project>") { projectDir } .defaultLazy("<project>") { projectDir }
internal val lockFile: String by option( internal val lockFile: String by option(
"--lock-file", "-l", "--lock-file",
"-l",
metavar = "FILENAME", metavar = "FILENAME",
help = "Name of the generated lock file" help = "Name of the generated lock file",
).default("gradle.lock") ).default("gradle.lock")
private val nixFile: String by option(
"--nix-file", "-n",
metavar = "FILENAME",
help = "Name of the generated Nix file"
).default("gradle.nix")
private val gradleSource: GradleSource by mutuallyExclusiveOptions( private val gradleSource: GradleSource by mutuallyExclusiveOptions(
option( option(
"--gradle-dist", "--gradle-dist",
metavar = "URI", metavar = "URI",
help = "Gradle distribution URI" help = "Gradle distribution URI",
).convert { GradleSource.Distribution(URI(it)) }, ).convert { GradleSource.Distribution(URI(it)) },
option( option(
"--gradle-home", "--gradle-home",
metavar = "DIR", metavar = "DIR",
help = "Gradle home path (e.g. \\`nix eval nixpkgs#gradle.outPath\\`/lib/gradle)" help = "Gradle home path (e.g. \\`nix eval --raw nixpkgs#gradle.outPath\\`/lib/gradle)",
).file(mustExist = true, canBeFile = false).convert { GradleSource.Path(it) }, ).file(mustExist = true, canBeFile = false).convert { GradleSource.Path(it) },
option( option(
"--gradle-wrapper", "--gradle-wrapper",
help = "Gradle wrapper version" help = "Gradle wrapper version",
).convert { GradleSource.Wrapper(it) }, ).convert { GradleSource.Wrapper(it) },
name = "Gradle installation", name = "Gradle installation",
help = "Where to find Gradle. By default, use the project's wrapper." help = "Where to find Gradle. By default, use the project's wrapper.",
).single().default(GradleSource.Project) ).single().default(GradleSource.Project)
private val gradleJdk: File? by option( private val gradleJdk: File? by option(
"--gradle-jdk", "-j", "--gradle-jdk",
"-j",
metavar = "DIR", metavar = "DIR",
help = "JDK home to use for launching Gradle (e.g. `nix eval nixpkgs#openjdk.home`)", help = "JDK home to use for launching Gradle (e.g. \\`nix eval --raw nixpkgs#openjdk.home\\`)",
).file(canBeFile = false, canBeDir = true) ).file(canBeFile = false, canBeDir = true)
private val logLevel: LogLevel by option( private val logLevel: LogLevel by option(
"--log", "--log",
help = "Print messages with this priority or higher") help = "Print messages with this priority or higher",
.enum<LogLevel>() )
.default(LogLevel.error) .enum<LogLevel>(key = { it.name.lowercase() })
.default(LogLevel.INFO, "info")
private val dumpEvents: Boolean by option( private val dumpEvents: Boolean by option(
"--dump-events", "--dump-events",
@@ -140,12 +143,12 @@ class Gradle2Nix : CliktCommand(
private val stacktrace: Boolean by option( private val stacktrace: Boolean by option(
"--stacktrace", "--stacktrace",
help = "Print a stack trace on error" help = "Print a stack trace on error",
).flag() ).flag()
private val gradleArgs: List<String> by argument( private val gradleArgs: List<String> by argument(
name = "ARGS", name = "ARGS",
help = "Extra arguments to pass to Gradle" help = "Extra arguments to pass to Gradle",
).multiple() ).multiple()
init { init {
@@ -158,11 +161,15 @@ class Gradle2Nix : CliktCommand(
override fun run() { override fun run() {
val logger = Logger(logLevel = logLevel, stacktrace = stacktrace) val logger = Logger(logLevel = logLevel, stacktrace = stacktrace)
val appHome = System.getProperty("org.nixos.gradle2nix.share")?.let(::File) val appHome =
?: error("could not locate the /share directory in the gradle2nix installation: ${System.getenv("APP_HOME")}") System.getProperty("org.nixos.gradle2nix.share")?.let(::File)
?: error("Could not locate the /share directory in the gradle2nix installation: ${System.getenv("APP_HOME")}")
logger.debug("appHome=$appHome")
val gradleHome = val gradleHome =
System.getenv("GRADLE_USER_HOME")?.let(::File) ?: File("${System.getProperty("user.home")}/.gradle") System.getenv("GRADLE_USER_HOME")?.let(::File) ?: File("${System.getProperty("user.home")}/.gradle")
val config = Config( logger.debug("gradleHome=$gradleHome")
val config =
Config(
appHome, appHome,
gradleHome, gradleHome,
gradleSource, gradleSource,
@@ -172,27 +179,14 @@ class Gradle2Nix : CliktCommand(
projectDir, projectDir,
tasks, tasks,
logger, logger,
dumpEvents dumpEvents,
) )
val metadata = File("$projectDir/gradle/verification-metadata.xml") val buildSrcs =
if (metadata.exists()) { connect(config).use { connection ->
val backup = metadata.resolveSibling("verification-metadata.xml.bak")
if (metadata.renameTo(backup)) {
Runtime.getRuntime().addShutdownHook(Thread {
metadata.delete()
backup.renameTo(metadata)
})
} else {
metadata.deleteOnExit()
}
} else {
metadata.deleteOnExit()
}
val buildSrcs = connect(config).use { connection ->
val root = runBlocking { connection.buildModel() } val root = runBlocking { connection.buildModel() }
val builds: List<GradleBuild> = buildList { val builds: List<GradleBuild> =
buildList {
add(root) add(root)
addAll(root.editableBuilds) addAll(root.editableBuilds)
} }
@@ -213,10 +207,11 @@ class Gradle2Nix : CliktCommand(
} }
} }
val env = try { val env =
try {
processDependencies(config, dependencySets) processDependencies(config, dependencySets)
} catch (e: Throwable) { } catch (e: Throwable) {
logger.error("dependency parsing failed", e) logger.error("Dependency parsing failed", e)
} }
config.outDir.mkdirs() config.outDir.mkdirs()
@@ -226,12 +221,6 @@ class Gradle2Nix : CliktCommand(
outLockFile.outputStream().buffered().use { output -> outLockFile.outputStream().buffered().use { output ->
JsonFormat.encodeToStream(env, output) JsonFormat.encodeToStream(env, output)
} }
val inNixFile = config.appHome.resolve("gradle.nix").takeIf { it.exists() }
?: error("Couldn't locate gradle.nix in the the gradle2nix installation: ${config.appHome}")
val outNixFile = config.outDir.resolve(nixFile)
logger.info("Writing Nix builder to $outNixFile")
inNixFile.copyTo(outNixFile, overwrite = true)
} }
} }

View File

@@ -1,12 +1,13 @@
package org.nixos.gradle2nix package org.nixos.gradle2nix
import okio.ByteString.Companion.decodeHex
import org.nixos.gradle2nix.model.DependencyCoordinates import org.nixos.gradle2nix.model.DependencyCoordinates
import org.nixos.gradle2nix.model.DependencySet import org.nixos.gradle2nix.model.DependencySet
import kotlin.io.encoding.Base64
import kotlin.io.encoding.ExperimentalEncodingApi
fun processDependencies( fun processDependencies(
config: Config, config: Config,
dependencySets: Iterable<DependencySet> dependencySets: Iterable<DependencySet>,
): Env { ): Env {
return buildMap<DependencyCoordinates, Map<String, Artifact>> { return buildMap<DependencyCoordinates, Map<String, Artifact>> {
for (dependencySet in dependencySets) { for (dependencySet in dependencySets) {
@@ -19,11 +20,13 @@ fun processDependencies(
for ((name, artifact) in b) { for ((name, artifact) in b) {
merge(name, artifact) { aa, ba -> merge(name, artifact) { aa, ba ->
check(aa.hash == ba.hash) { check(aa.hash == ba.hash) {
config.logger.error(""" config.logger.error(
"""
Conflicting hashes found for $id:$name: Conflicting hashes found for $id:$name:
1: ${aa.hash} 1: ${aa.hash}
2: ${ba.hash} 2: ${ba.hash}
""".trimIndent()) """.trimIndent(),
)
} }
aa aa
@@ -41,18 +44,22 @@ fun processDependencies(
private fun DependencySet.toEnv(): Map<DependencyCoordinates, Map<String, Artifact>> { private fun DependencySet.toEnv(): Map<DependencyCoordinates, Map<String, Artifact>> {
return dependencies.associate { dep -> return dependencies.associate { dep ->
dep.coordinates to dep.artifacts.associate { dep.coordinates to
dep.artifacts.associate {
it.name to Artifact(it.url, it.hash.toSri()) it.name to Artifact(it.url, it.hash.toSri())
} }
} }
} }
internal fun String.toSri(): String { @OptIn(ExperimentalEncodingApi::class, ExperimentalStdlibApi::class)
val hash = decodeHex().base64() internal fun String.toSri(): String =
return "sha256-$hash" buildString {
} append("sha256-")
Base64.encodeToAppendable(hexToByteArray(), this)
}
private val coordinatesComparator: Comparator<DependencyCoordinates> = compareBy<DependencyCoordinates> { it.group } private val coordinatesComparator: Comparator<DependencyCoordinates> =
compareBy<DependencyCoordinates> { it.group }
.thenBy { it.artifact } .thenBy { it.artifact }
.thenByDescending { Version(it.version) } .thenByDescending { Version(it.version) }
.thenByDescending { it.timestamp } .thenByDescending { it.timestamp }

View File

@@ -2,5 +2,13 @@ package org.nixos.gradle2nix
import java.io.File import java.io.File
fun File.isProjectRoot(): Boolean = tailrec fun getProjectRoot(path: File): File? {
isDirectory && (resolve("settings.gradle").isFile || resolve("settings.gradle.kts").isFile) return if (path.isProjectRoot()) {
path
} else {
val parent = path.parentFile ?: return null
return getProjectRoot(parent)
}
}
fun File.isProjectRoot(): Boolean = isDirectory && (resolve("settings.gradle").isFile || resolve("settings.gradle.kts").isFile)

View File

@@ -3,14 +3,18 @@ package org.nixos.gradle2nix
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
class Version(val source: String, val parts: List<String>, base: Version?) : Comparable<Version> { class Version(val source: String, val parts: List<String>, base: Version?) : Comparable<Version> {
private val base: Version private val base: Version
val numericParts: List<Long?> val numericParts: List<Long?>
init { init {
this.base = base ?: this this.base = base ?: this
this.numericParts = parts.map { this.numericParts =
try { it.toLong() } catch (e: NumberFormatException) { null } parts.map {
try {
it.toLong()
} catch (e: NumberFormatException) {
null
}
} }
} }
@@ -18,7 +22,8 @@ class Version(val source: String, val parts: List<String>, base: Version?) : Com
override fun toString(): String = source override fun toString(): String = source
override fun equals(other: Any?): Boolean = when { override fun equals(other: Any?): Boolean =
when {
other === this -> true other === this -> true
other == null || other !is Version -> false other == null || other !is Version -> false
else -> source == other.source else -> source == other.source
@@ -27,20 +32,22 @@ class Version(val source: String, val parts: List<String>, base: Version?) : Com
override fun hashCode(): Int = source.hashCode() override fun hashCode(): Int = source.hashCode()
companion object { companion object {
private val SPECIAL_MEANINGS: Map<String, Int> = mapOf( private val SPECIAL_MEANINGS: Map<String, Int> =
mapOf(
"dev" to -1, "dev" to -1,
"rc" to 1, "rc" to 1,
"snapshot" to 2, "snapshot" to 2,
"final" to 3, "final" to 3,
"ga" to 4, "ga" to 4,
"release" to 5, "release" to 5,
"sp" to 6 "sp" to 6,
) )
private val cache = ConcurrentHashMap<String, Version>() private val cache = ConcurrentHashMap<String, Version>()
// From org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionParser // From org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionParser
operator fun invoke(original: String): Version = cache.getOrPut(original) { operator fun invoke(original: String): Version =
cache.getOrPut(original) {
val parts = mutableListOf<String>() val parts = mutableListOf<String>()
var digit = false var digit = false
var startPart = 0 var startPart = 0
@@ -91,7 +98,10 @@ class Version(val source: String, val parts: List<String>, base: Version?) : Com
} }
// From org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.StaticVersionComparator // From org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.StaticVersionComparator
private fun compare(version1: Version, version2: Version): Int { private fun compare(
version1: Version,
version2: Version,
): Int {
if (version1 == version2) { if (version1 == version2) {
return 0 return 0
} }

View File

@@ -21,11 +21,6 @@ import io.ktor.server.http.content.staticFiles
import io.ktor.server.netty.Netty import io.ktor.server.netty.Netty
import io.ktor.server.netty.NettyApplicationEngine import io.ktor.server.netty.NettyApplicationEngine
import io.ktor.server.routing.routing import io.ktor.server.routing.routing
import java.io.File
import java.io.FileFilter
import java.nio.file.Files
import java.nio.file.Paths
import kotlin.random.Random
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -35,17 +30,22 @@ import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromStream import kotlinx.serialization.json.decodeFromStream
import kotlinx.serialization.json.encodeToStream import kotlinx.serialization.json.encodeToStream
import okio.use import java.io.File
import java.io.FileFilter
import java.nio.file.Files
import java.nio.file.Paths
import kotlin.random.Random
private val app = Gradle2Nix() private val app = Gradle2Nix()
@OptIn(ExperimentalSerializationApi::class) @OptIn(ExperimentalSerializationApi::class)
private val json = Json { private val json =
Json {
prettyPrint = true prettyPrint = true
prettyPrintIndent = " " prettyPrintIndent = " "
} }
val testLogger = Logger(logLevel = LogLevel.debug, stacktrace = true) val testLogger = Logger(logLevel = LogLevel.DEBUG, stacktrace = true)
fun fixture(path: String): File { fun fixture(path: String): File {
return Paths.get("../fixtures", path).toFile() return Paths.get("../fixtures", path).toFile()
@@ -55,13 +55,15 @@ fun fixture(path: String): File {
suspend fun TestScope.fixture( suspend fun TestScope.fixture(
project: String, project: String,
vararg args: String, vararg args: String,
test: suspend TestScope.(File, Env) -> Unit test: suspend TestScope.(File, Env) -> Unit,
) { ) {
val tmp = Paths.get("build/tmp/gradle2nix").apply { toFile().mkdirs() } val tmp = Paths.get("build/tmp/gradle2nix").apply { toFile().mkdirs() }
val baseDir = Paths.get("../fixtures/projects", project).toFile() val baseDir = Paths.get("../fixtures/projects", project).toFile()
val children = baseDir.listFiles(FileFilter { it.isDirectory && (it.name == "groovy" || it.name == "kotlin") }) val children =
baseDir.listFiles(FileFilter { it.isDirectory && (it.name == "groovy" || it.name == "kotlin") })
?.toList() ?.toList()
val cases = if (children.isNullOrEmpty()) { val cases =
if (children.isNullOrEmpty()) {
listOf(project to baseDir) listOf(project to baseDir)
} else { } else {
children.map { "$project.${it.name}" to it } children.map { "$project.${it.name}" to it }
@@ -73,7 +75,7 @@ suspend fun TestScope.fixture(
disabled = false, disabled = false,
config = null, config = null,
type = TestType.Dynamic, type = TestType.Dynamic,
source = sourceRef() source = sourceRef(),
) { ) {
var dirName = case.second.toString().replace("/", ".") var dirName = case.second.toString().replace("/", ".")
while (dirName.startsWith(".")) dirName = dirName.removePrefix(".") while (dirName.startsWith(".")) dirName = dirName.removePrefix(".")
@@ -88,22 +90,25 @@ suspend fun TestScope.fixture(
} }
app.main( app.main(
listOf( listOf(
"-p", tempDir.toString(), "-p",
"--log", "debug", tempDir.toString(),
"--log",
"debug",
"--stacktrace", "--stacktrace",
"--dump-events", "--dump-events",
"--", "--",
"-Dorg.nixos.gradle2nix.m2=$m2", "-Dorg.nixos.gradle2nix.m2=$m2",
"--info" "--info",
) + args ) + args,
) )
val file = tempDir.resolve(app.lockFile) val file = tempDir.resolve(app.lockFile)
file.shouldBeAFile() file.shouldBeAFile()
val env: Env = file.inputStream().buffered().use { input -> val env: Env =
file.inputStream().buffered().use { input ->
Json.decodeFromStream(input) Json.decodeFromStream(input)
} }
test(tempDir, env) test(tempDir, env)
} },
) )
} }
} }
@@ -127,7 +132,8 @@ suspend fun TestScope.golden(
if (!goldenFile.exists()) { if (!goldenFile.exists()) {
fail("Golden file '$filename' doesn't exist. Run with --update-golden to generate.") fail("Golden file '$filename' doesn't exist. Run with --update-golden to generate.")
} }
val goldenData = try { val goldenData =
try {
goldenFile.readText() goldenFile.readText()
} catch (e: SerializationException) { } catch (e: SerializationException) {
fail("Failed to load golden data from '$filename'. Run with --update-golden to regenerate.") fail("Failed to load golden data from '$filename'. Run with --update-golden to regenerate.")
@@ -172,7 +178,8 @@ object MavenRepo : MountableExtension<MavenRepo.Config, NettyApplicationEngine>,
private fun tryStart(attempts: Int): NettyApplicationEngine { private fun tryStart(attempts: Int): NettyApplicationEngine {
return try { return try {
val p = config.port ?: Random.nextInt(10000, 65000) val p = config.port ?: Random.nextInt(10000, 65000)
val s = embeddedServer(Netty, port = p, host = config.host) { val s =
embeddedServer(Netty, port = p, host = config.host) {
routing { routing {
staticFiles( staticFiles(
remotePath = config.path, remotePath = config.path,

View File

@@ -1,9 +1,11 @@
{ pkgs ? import <nixpkgs> {} }: {
pkgs ? import <nixpkgs> { },
}:
with pkgs; with pkgs;
let let
buildGradlePackage = callPackage ./gradle.nix {}; buildGradlePackage = callPackage ./gradle.nix { };
gradle2nix = buildGradlePackage { gradle2nix = buildGradlePackage {
pname = "gradle2nix"; pname = "gradle2nix";
@@ -13,13 +15,14 @@ let
src = lib.cleanSourceWith { src = lib.cleanSourceWith {
filter = lib.cleanSourceFilter; filter = lib.cleanSourceFilter;
src = lib.cleanSourceWith { src = lib.cleanSourceWith {
filter = path: type: let baseName = baseNameOf path; in !( filter =
(type == "directory" && ( path: type:
baseName == "build" || let
baseName == ".idea" || baseName = baseNameOf path;
baseName == ".gradle" in
)) || !(
(lib.hasSuffix ".iml" baseName) (type == "directory" && (baseName == "build" || baseName == ".idea" || baseName == ".gradle"))
|| (lib.hasSuffix ".iml" baseName)
); );
src = ./.; src = ./.;
}; };
@@ -28,13 +31,14 @@ let
gradleFlags = [ "installDist" ]; gradleFlags = [ "installDist" ];
installPhase = '' installPhase = ''
mkdir -p $out mkdir -p $out/{bin,/lib/gradle2nix}
cp -r app/build/install/gradle2nix/* $out/ cp -r app/build/install/gradle2nix/* $out/lib/gradle2nix/
rm $out/lib/gradle2nix/bin/gradle2nix.bat
ln -sf $out/lib/gradle2nix/bin/gradle2nix $out/bin
''; '';
passthru = { passthru = {
inherit buildGradlePackage; inherit buildGradlePackage;
plugin = "${gradle2nix}/share/plugin.jar";
}; };
meta = with lib; { meta = with lib; {
@@ -46,5 +50,5 @@ let
mainProgram = "gradle2nix"; mainProgram = "gradle2nix";
}; };
}; };
in
in gradle2nix gradle2nix

View File

@@ -0,0 +1 @@
// Intentionally left empty

View File

@@ -0,0 +1 @@
// Intentionally left empty

View File

@@ -0,0 +1 @@
// Intentionally left empty

View File

@@ -0,0 +1 @@
// Intentionally left empty

View File

@@ -0,0 +1 @@
// Intentionally left empty

View File

@@ -0,0 +1 @@
// Intentionally left empty

View File

@@ -0,0 +1 @@
// Intentionally left empty

View File

@@ -0,0 +1 @@
// Intentionally left empty

View File

@@ -1,9 +1,9 @@
with (import <nixpkgs> {}); with (import <nixpkgs> { });
let let
buildGradle = callPackage ./gradle-env.nix {}; buildGradle = callPackage ./gradle-env.nix { };
in in
buildGradle { buildGradle {
envSpec = ./gradle-env.json; envSpec = ./gradle-env.json;
src = ./.; src = ./.;
gradleFlags = [ "tasks" ]; gradleFlags = [ "tasks" ];
} }

View File

@@ -19,32 +19,59 @@
# ''; # '';
# } # }
{ stdenv, buildEnv, fetchurl, gradleGen, writeText, writeTextDir }: {
stdenv,
buildEnv,
fetchurl,
gradleGen,
writeText,
writeTextDir,
}:
{ envSpec {
, pname ? null envSpec,
, version ? null pname ? null,
, enableParallelBuilding ? true version ? null,
, gradleFlags ? [ "build" ] enableParallelBuilding ? true,
, gradlePackage ? null gradleFlags ? [ "build" ],
, enableDebug ? false gradlePackage ? null,
, ... } @ args: enableDebug ? false,
...
}@args:
let let
inherit (builtins) inherit (builtins)
attrValues concatStringsSep filter fromJSON match replaceStrings sort; attrValues
concatStringsSep
filter
fromJSON
match
replaceStrings
sort
;
inherit (stdenv.lib) inherit (stdenv.lib)
assertMsg concatMapStringsSep groupBy' hasSuffix last mapAttrs assertMsg
mapAttrsToList optionalString readFile removeSuffix unique versionAtLeast concatMapStringsSep
versionOlder; groupBy'
hasSuffix
last
mapAttrs
mapAttrsToList
optionalString
readFile
removeSuffix
unique
versionAtLeast
versionOlder
;
mkDep = depSpec: stdenv.mkDerivation { mkDep =
depSpec:
stdenv.mkDerivation {
inherit (depSpec) name; inherit (depSpec) name;
src = fetchurl { src = fetchurl { inherit (depSpec) urls sha256; };
inherit (depSpec) urls sha256;
};
phases = "installPhase"; phases = "installPhase";
@@ -54,41 +81,43 @@ let
''; '';
}; };
mkModuleMetadata = deps: mkModuleMetadata =
deps:
let let
ids = filter ids = filter (id: id.type == "pom") (map (dep: dep.id) deps);
(id: id.type == "pom")
(map (dep: dep.id) deps);
modules = groupBy' modules =
(meta: id: groupBy'
(
meta: id:
let let
isNewer = versionOlder meta.latest id.version; isNewer = versionOlder meta.latest id.version;
isNewerRelease = isNewerRelease = !(hasSuffix "-SNAPSHOT" id.version) && versionOlder meta.release id.version;
!(hasSuffix "-SNAPSHOT" id.version) && in
versionOlder meta.release id.version; {
in {
groupId = id.group; groupId = id.group;
artifactId = id.name; artifactId = id.name;
latest = if isNewer then id.version else meta.latest; latest = if isNewer then id.version else meta.latest;
release = if isNewerRelease then id.version else meta.release; release = if isNewerRelease then id.version else meta.release;
versions = meta.versions ++ [id.version]; versions = meta.versions ++ [ id.version ];
} }
) )
{ {
latest = ""; latest = "";
release = ""; release = "";
versions = []; versions = [ ];
} }
(id: "${replaceStrings ["."] ["/"] id.group}/${id.name}/maven-metadata.xml") (id: "${replaceStrings [ "." ] [ "/" ] id.group}/${id.name}/maven-metadata.xml")
ids; ids;
in in
attrValues (mapAttrs (path: meta: attrValues (
mapAttrs (
path: meta:
let let
versions' = sort versionOlder (unique meta.versions); versions' = sort versionOlder (unique meta.versions);
in in
with meta; writeTextDir path '' with meta;
writeTextDir path ''
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<metadata modelVersion="1.1"> <metadata modelVersion="1.1">
<groupId>${groupId}</groupId> <groupId>${groupId}</groupId>
@@ -102,34 +131,43 @@ let
</versioning> </versioning>
</metadata> </metadata>
'' ''
) modules); ) modules
);
mkSnapshotMetadata = deps: mkSnapshotMetadata =
deps:
let let
snapshotDeps = filter (dep: dep ? build && dep ? timestamp) deps; snapshotDeps = filter (dep: dep ? build && dep ? timestamp) deps;
modules = groupBy' modules =
(meta: dep: groupBy'
(
meta: dep:
let let
id = dep.id; id = dep.id;
isNewer = dep.build > meta.buildNumber; isNewer = dep.build > meta.buildNumber;
# Timestamp values can be bogus, e.g. jitpack.io # Timestamp values can be bogus, e.g. jitpack.io
updated = if (match "[0-9]{8}\.[0-9]{6}" dep.timestamp) != null updated =
then replaceStrings ["."] [""] dep.timestamp if (match "[0-9]{8}\.[0-9]{6}" dep.timestamp) != null then
else ""; replaceStrings [ "." ] [ "" ] dep.timestamp
in { else
"";
in
{
groupId = id.group; groupId = id.group;
artifactId = id.name; artifactId = id.name;
version = id.version; version = id.version;
timestamp = if isNewer then dep.timestamp else meta.timestamp; timestamp = if isNewer then dep.timestamp else meta.timestamp;
buildNumber = if isNewer then dep.build else meta.buildNumber; buildNumber = if isNewer then dep.build else meta.buildNumber;
lastUpdated = if isNewer then updated else meta.lastUpdated; lastUpdated = if isNewer then updated else meta.lastUpdated;
versions = meta.versions or [] ++ [{ versions = meta.versions or [ ] ++ [
{
classifier = id.classifier or ""; classifier = id.classifier or "";
extension = id.extension; extension = id.extension;
value = "${removeSuffix "-SNAPSHOT" id.version}-${dep.timestamp}-${toString dep.build}"; value = "${removeSuffix "-SNAPSHOT" id.version}-${dep.timestamp}-${toString dep.build}";
updated = updated; updated = updated;
}]; }
];
} }
) )
{ {
@@ -137,7 +175,10 @@ let
buildNumber = -1; buildNumber = -1;
lastUpdated = ""; lastUpdated = "";
} }
(dep: "${replaceStrings ["."] ["/"] dep.id.group}/${dep.id.name}/${dep.id.version}/maven-metadata.xml") (
dep:
"${replaceStrings [ "." ] [ "/" ] dep.id.group}/${dep.id.name}/${dep.id.version}/maven-metadata.xml"
)
snapshotDeps; snapshotDeps;
mkSnapshotVersion = version: '' mkSnapshotVersion = version: ''
@@ -148,10 +189,12 @@ let
${optionalString (version.updated != "") "<updated>${version.updated}</updated>"} ${optionalString (version.updated != "") "<updated>${version.updated}</updated>"}
</snapshotVersion> </snapshotVersion>
''; '';
in in
attrValues (mapAttrs (path: meta: attrValues (
with meta; writeTextDir path '' mapAttrs (
path: meta:
with meta;
writeTextDir path ''
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<metadata modelVersion="1.1"> <metadata modelVersion="1.1">
<groupId>${groupId}</groupId> <groupId>${groupId}</groupId>
@@ -169,26 +212,32 @@ let
</versioning> </versioning>
</metadata> </metadata>
'' ''
) modules); ) modules
);
mkRepo = project: type: deps: buildEnv { mkRepo =
project: type: deps:
buildEnv {
name = "${project}-gradle-${type}-env"; name = "${project}-gradle-${type}-env";
paths = map mkDep deps ++ mkModuleMetadata deps ++ mkSnapshotMetadata deps; paths = map mkDep deps ++ mkModuleMetadata deps ++ mkSnapshotMetadata deps;
}; };
mkInitScript = projectSpec: gradle: mkInitScript =
projectSpec: gradle:
let let
repos = mapAttrs (mkRepo projectSpec.name) projectSpec.dependencies; repos = mapAttrs (mkRepo projectSpec.name) projectSpec.dependencies;
hasDependencies = mapAttrs (type: deps: deps != []) projectSpec.dependencies; hasDependencies = mapAttrs (type: deps: deps != [ ]) projectSpec.dependencies;
in in
assert (assertMsg (hasDependencies.settings -> versionAtLeast gradle.version "6.0") '' assert (
assertMsg (hasDependencies.settings -> versionAtLeast gradle.version "6.0") ''
Project `${projectSpec.name}' has settings script dependencies, such as settings Project `${projectSpec.name}' has settings script dependencies, such as settings
plugins, which are not supported by gradle2nix for Gradle versions prior to 6.0. plugins, which are not supported by gradle2nix for Gradle versions prior to 6.0.
Potential remedies: Potential remedies:
- Pass `--gradle-version=<version>' to the gradle2nix command. - Pass `--gradle-version=<version>' to the gradle2nix command.
- Patch the `settings.gradle[.kts]' file to remove script dependencies. - Patch the `settings.gradle[.kts]' file to remove script dependencies.
''); ''
);
writeText "init.gradle" '' writeText "init.gradle" ''
static def offlineRepo(RepositoryHandler repositories, String env, String path) { static def offlineRepo(RepositoryHandler repositories, String env, String path) {
@@ -245,16 +294,16 @@ let
''} ''}
''; '';
mkGradle = gradleSpec: mkGradle =
gradleSpec:
gradleGen.gradleGen { gradleGen.gradleGen {
inherit (gradleSpec) nativeVersion; inherit (gradleSpec) nativeVersion;
name = "gradle-${gradleSpec.version}-${gradleSpec.type}"; name = "gradle-${gradleSpec.version}-${gradleSpec.type}";
src = fetchurl { src = fetchurl { inherit (gradleSpec) url sha256; };
inherit (gradleSpec) url sha256; }
}; // {
} // {
inherit (gradleSpec) version; inherit (gradleSpec) version;
}; };
@@ -264,9 +313,7 @@ let
initScript = mkInitScript projectSpec gradle; initScript = mkInitScript projectSpec gradle;
}; };
gradleEnv = mapAttrs gradleEnv = mapAttrs (_: p: mkProjectEnv p) (fromJSON (readFile envSpec));
(_: p: mkProjectEnv p)
(fromJSON (readFile envSpec));
projectEnv = gradleEnv.""; projectEnv = gradleEnv."";
pname = args.pname or projectEnv.name; pname = args.pname or projectEnv.name;
@@ -282,20 +329,22 @@ let
${concatStringsSep " " flags} ${concatStringsSep " " flags}
''; '';
buildIncludedProjects = buildIncludedProjects = concatStringsSep "\n" (
concatStringsSep "\n" (mapAttrsToList mapAttrsToList (_: env: buildProject env [ "build" ]) (removeAttrs gradleEnv [ "" ])
(_: env: buildProject env [ "build" ]) );
(removeAttrs gradleEnv [ "" ]));
buildRootProject = buildProject projectEnv gradleFlags; buildRootProject = buildProject projectEnv gradleFlags;
in
in stdenv.mkDerivation (args // { stdenv.mkDerivation (
args
// {
inherit pname version; inherit pname version;
nativeBuildInputs = (args.nativeBuildInputs or []) ++ [ projectEnv.gradle ]; nativeBuildInputs = (args.nativeBuildInputs or [ ]) ++ [ projectEnv.gradle ];
buildPhase = args.buildPhase or '' buildPhase =
args.buildPhase or ''
runHook preBuild runHook preBuild
( (
@@ -315,4 +364,5 @@ in stdenv.mkDerivation (args // {
''; '';
dontStrip = true; dontStrip = true;
}) }
)

View File

@@ -0,0 +1 @@
// Intentionally left empty

View File

@@ -0,0 +1 @@
// Intentionally left empty

View File

@@ -0,0 +1 @@
// Intentionally left empty

View File

@@ -0,0 +1 @@
// Intentionally left empty

8
flake.lock generated
View File

@@ -20,16 +20,16 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1715954240, "lastModified": 1716769173,
"narHash": "sha256-eC0zRYkazBc2cKz1VSzMLvCc9uHXlSQEr1Be+c5UV1w=", "narHash": "sha256-7EXDb5WBw+d004Agt+JHC/Oyh/KTUglOaQ4MNjBbo5w=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "c2ea18b50a4c7fcb7c90402166769bf3b82b5aa9", "rev": "9ca3f649614213b2aaf5f1e16ec06952fe4c2632",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "nixos-unstable-small", "ref": "nixos-unstable",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }

View File

@@ -3,22 +3,49 @@
inputs = { inputs = {
flake-utils.url = "github:numtide/flake-utils"; flake-utils.url = "github:numtide/flake-utils";
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable-small"; nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
}; };
outputs = { self, flake-utils, nixpkgs, ... }: outputs =
flake-utils.lib.eachDefaultSystem (system: {
self,
flake-utils,
nixpkgs,
...
}:
flake-utils.lib.eachDefaultSystem (
system:
let let
pkgs = nixpkgs.legacyPackages.${system}; pkgs = nixpkgs.legacyPackages.${system};
inherit (nixpkgs) lib;
in { in
builders.default = pkgs.callPackage ./gradle.nix {}; {
builders = rec {
packages.default = pkgs.callPackage ./default.nix {}; buildGradlePackage = pkgs.callPackage ./gradle.nix { };
default = buildGradlePackage;
apps.default = {
type = "app";
program = "${self.packages.${system}.default}/bin/gradle2nix";
}; };
});
packages = rec {
gradle2nix = pkgs.callPackage ./default.nix { };
default = gradle2nix;
};
apps = rec {
gradle2nix = {
type = "app";
program = lib.getExe self.packages.${system}.default;
};
default = gradle2nix;
};
formatter = pkgs.writeShellScriptBin "gradle2nix-fmt" ''
fail=0
${lib.getExe pkgs.nixfmt-rfc-style} $@ || fail=1
${lib.getExe pkgs.ktlint} --relative -l warn -F || fail=1
[ $fail -eq 0 ] || echo "Formatting failed." >&2
exit $fail
'';
}
);
} }

View File

@@ -161,34 +161,6 @@
"hash": "sha256-E6X+iu2+Rs/b6hLp/NcJemKygqpqtMkIZWuWzpoqX6M=" "hash": "sha256-E6X+iu2+Rs/b6hLp/NcJemKygqpqtMkIZWuWzpoqX6M="
} }
}, },
"com.squareup.okio:okio:3.9.0": {
"okio-3.9.0.jar": {
"url": "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/3.9.0/okio-3.9.0.jar",
"hash": "sha256-5RilmFYnOh/OGKx9E938aQ3vphItflzQDK4Zti0DR9k="
},
"okio-3.9.0.module": {
"url": "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/3.9.0/okio-3.9.0.module",
"hash": "sha256-aNHIef9liTHQKzrb6vu1EuFjwgqQyt8H2QyNvqfnYhA="
},
"okio-3.9.0.pom": {
"url": "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/3.9.0/okio-3.9.0.pom",
"hash": "sha256-FPNR2puXtDaeP26PaWsK1ANtFNIbD9l6pcjG7BW+fZA="
}
},
"com.squareup.okio:okio-jvm:3.9.0": {
"okio-jvm-3.9.0.jar": {
"url": "https://repo.maven.apache.org/maven2/com/squareup/okio/okio-jvm/3.9.0/okio-jvm-3.9.0.jar",
"hash": "sha256-3cOG/xS9JdXJNBZxlur0WxjeTyjhxVpNs3rllMv9N+Q="
},
"okio-jvm-3.9.0.module": {
"url": "https://repo.maven.apache.org/maven2/com/squareup/okio/okio-jvm/3.9.0/okio-jvm-3.9.0.module",
"hash": "sha256-z5coTsYbtR5t/Lx/K22VVsm3s+PLIswOLU8O7782GVs="
},
"okio-jvm-3.9.0.pom": {
"url": "https://repo.maven.apache.org/maven2/com/squareup/okio/okio-jvm/3.9.0/okio-jvm-3.9.0.pom",
"hash": "sha256-VEiNRUqsyvaPcZnz3l3Ns4CBblfUYJBJF06FZSAROH4="
}
},
"com.typesafe:config:1.4.3": { "com.typesafe:config:1.4.3": {
"config-1.4.3.jar": { "config-1.4.3.jar": {
"url": "https://repo.maven.apache.org/maven2/com/typesafe/config/1.4.3/config-1.4.3.jar", "url": "https://repo.maven.apache.org/maven2/com/typesafe/config/1.4.3/config-1.4.3.jar",
@@ -241,48 +213,6 @@
"hash": "sha256-2BHPnxGMwsrRMMlCetVcF01MCm8aAKwa4cm8vsXESxk=" "hash": "sha256-2BHPnxGMwsrRMMlCetVcF01MCm8aAKwa4cm8vsXESxk="
} }
}, },
"io.github.pdvrieze.xmlutil:core:0.86.3": {
"core-0.86.3.jar": {
"url": "https://repo.maven.apache.org/maven2/io/github/pdvrieze/xmlutil/core/0.86.3/core-0.86.3.jar",
"hash": "sha256-ikZHG7Y7PHhzlsu6WqL2TU4zOgOSAiRBrhIRHn5yjJE="
},
"core-0.86.3.module": {
"url": "https://repo.maven.apache.org/maven2/io/github/pdvrieze/xmlutil/core/0.86.3/core-0.86.3.module",
"hash": "sha256-MzlXsdCR2LrPqwYCCGgi+a2S9hMCy3Ru8g4Z9nprTbk="
},
"core-0.86.3.pom": {
"url": "https://repo.maven.apache.org/maven2/io/github/pdvrieze/xmlutil/core/0.86.3/core-0.86.3.pom",
"hash": "sha256-ngeyUCJI+U7AYn9Wsn3wiBySBCrfzoCg35oa6sQWg4M="
}
},
"io.github.pdvrieze.xmlutil:core-jvm:0.86.3": {
"core-jvm-0.86.3.jar": {
"url": "https://repo.maven.apache.org/maven2/io/github/pdvrieze/xmlutil/core-jvm/0.86.3/core-jvm-0.86.3.jar",
"hash": "sha256-kVJ9hv6gS9YYPRQKCfENqy3qcnrxLSfZFl7jQuo9Dt4="
},
"core-jvm-0.86.3.module": {
"url": "https://repo.maven.apache.org/maven2/io/github/pdvrieze/xmlutil/core-jvm/0.86.3/core-jvm-0.86.3.module",
"hash": "sha256-FgIJExZWo2dDGWXYAYk7J3fuguD3ZmaD+nXE+Wck/wc="
},
"core-jvm-0.86.3.pom": {
"url": "https://repo.maven.apache.org/maven2/io/github/pdvrieze/xmlutil/core-jvm/0.86.3/core-jvm-0.86.3.pom",
"hash": "sha256-oBGIoPlVW1s7nZLlQz242AJ6vjleD/cIBRU+8v6qf4U="
}
},
"io.github.pdvrieze.xmlutil:serialization-jvm:0.86.3": {
"serialization-jvm-0.86.3.jar": {
"url": "https://repo.maven.apache.org/maven2/io/github/pdvrieze/xmlutil/serialization-jvm/0.86.3/serialization-jvm-0.86.3.jar",
"hash": "sha256-nOJz3LhguSpb8uw2rR4qEbQa7YnGyYTKc+h+/17aG9A="
},
"serialization-jvm-0.86.3.module": {
"url": "https://repo.maven.apache.org/maven2/io/github/pdvrieze/xmlutil/serialization-jvm/0.86.3/serialization-jvm-0.86.3.module",
"hash": "sha256-3ppDm3mA++bMPDS8rZyEqIMVmdyHZNceD2c93Ho91Jo="
},
"serialization-jvm-0.86.3.pom": {
"url": "https://repo.maven.apache.org/maven2/io/github/pdvrieze/xmlutil/serialization-jvm/0.86.3/serialization-jvm-0.86.3.pom",
"hash": "sha256-OX1XqPVTaUEf7HRETH1NTLaeyYANUkSTrGHekJIl4wc="
}
},
"io.kotest:kotest-assertions-api:5.9.0": { "io.kotest:kotest-assertions-api:5.9.0": {
"kotest-assertions-api-5.9.0.jar": { "kotest-assertions-api-5.9.0.jar": {
"url": "https://repo.maven.apache.org/maven2/io/kotest/kotest-assertions-api/5.9.0/kotest-assertions-api-5.9.0.jar", "url": "https://repo.maven.apache.org/maven2/io/kotest/kotest-assertions-api/5.9.0/kotest-assertions-api-5.9.0.jar",
@@ -1039,16 +969,6 @@
"hash": "sha256-4E4llRUB3yWtx7Hc22xTNzyUiXuE0+FJISknY+4Hrj0=" "hash": "sha256-4E4llRUB3yWtx7Hc22xTNzyUiXuE0+FJISknY+4Hrj0="
} }
}, },
"net.java.dev.jna:jna:5.9.0": {
"jna-5.9.0.jar": {
"url": "https://repo.maven.apache.org/maven2/net/java/dev/jna/jna/5.9.0/jna-5.9.0.jar",
"hash": "sha256-6vzHgLRFQ008Wuf6L7ZmXeGnVg1TfSxAio6AzRTScWE="
},
"jna-5.9.0.pom": {
"url": "https://repo.maven.apache.org/maven2/net/java/dev/jna/jna/5.9.0/jna-5.9.0.pom",
"hash": "sha256-a8i4RZFQtZ6VmPPa2a0kWh7yFQ0IJYEBcYTrFj5ZKCk="
}
},
"net.java.dev.jna:jna-platform:5.9.0": { "net.java.dev.jna:jna-platform:5.9.0": {
"jna-platform-5.9.0.jar": { "jna-platform-5.9.0.jar": {
"url": "https://repo.maven.apache.org/maven2/net/java/dev/jna/jna-platform/5.9.0/jna-platform-5.9.0.jar", "url": "https://repo.maven.apache.org/maven2/net/java/dev/jna/jna-platform/5.9.0/jna-platform-5.9.0.jar",
@@ -1331,214 +1251,224 @@
"hash": "sha256-h3IcuqZaPJfYsbqdIHhA8WTJ/jh1n8nqEP/iZWX40+k=" "hash": "sha256-h3IcuqZaPJfYsbqdIHhA8WTJ/jh1n8nqEP/iZWX40+k="
} }
}, },
"org.jetbrains.kotlin:kotlin-android-extensions:1.9.22": { "org.jetbrains.kotlin:kotlin-android-extensions:1.9.24": {
"kotlin-android-extensions-1.9.22.jar": { "kotlin-android-extensions-1.9.24.jar": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-android-extensions/1.9.22/kotlin-android-extensions-1.9.22.jar", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-android-extensions/1.9.24/kotlin-android-extensions-1.9.24.jar",
"hash": "sha256-Hl6IFkKpnduPbRPmmVoIwZK8OEGHOWZj2ER8CB2H4k8=" "hash": "sha256-4z5UUlSR0ZgdRODKmnxTIWh91QRDPsVJZhqb5UYKEW4="
}, },
"kotlin-android-extensions-1.9.22.pom": { "kotlin-android-extensions-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-android-extensions/1.9.22/kotlin-android-extensions-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-android-extensions/1.9.24/kotlin-android-extensions-1.9.24.pom",
"hash": "sha256-lEt8+zPgpvtoRVkEjwKMuWMmyTKiRdXLAhQ7zSwDEVk=" "hash": "sha256-6QmjYHLn/lbQULgKdXEDwdP4dz+2wb0GcrxKr7hRCEs="
} }
}, },
"org.jetbrains.kotlin:kotlin-build-common:1.9.22": { "org.jetbrains.kotlin:kotlin-build-common:1.9.24": {
"kotlin-build-common-1.9.22.jar": { "kotlin-build-common-1.9.24.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-build-common/1.9.22/kotlin-build-common-1.9.22.jar", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-build-common/1.9.24/kotlin-build-common-1.9.24.jar",
"hash": "sha256-U8PcxTA/WQPmJgrqc+zMaTD5o276KhHNO9On5V32OWY=" "hash": "sha256-+RqOaTfik7FEv6F0DHB3xa12EdtI9CnKMcCm2yduaUo="
}, },
"kotlin-build-common-1.9.22.pom": { "kotlin-build-common-1.9.24.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-build-common/1.9.22/kotlin-build-common-1.9.22.pom", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-build-common/1.9.24/kotlin-build-common-1.9.24.pom",
"hash": "sha256-KXxfSYoHdIPvic06cQzSt/LlrjgPOjrt+5xBvGI7E0A=" "hash": "sha256-iNt6ER1bfbV+4gKFEX2mNz3NJQQxqd58h8ZCJRYL0RI="
} }
}, },
"org.jetbrains.kotlin:kotlin-build-tools-api:1.9.22": { "org.jetbrains.kotlin:kotlin-build-tools-api:1.9.24": {
"kotlin-build-tools-api-1.9.22.jar": { "kotlin-build-tools-api-1.9.24.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-build-tools-api/1.9.22/kotlin-build-tools-api-1.9.22.jar", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-build-tools-api/1.9.24/kotlin-build-tools-api-1.9.24.jar",
"hash": "sha256-3UnLfij08zgvUlDPsFyGT9XwqW0yZbspPHezCtzJP/Y=" "hash": "sha256-ZUX99qL/t4jN3O3KymMiOdx+XmHD90SCNzXjse2cG1Q="
}, },
"kotlin-build-tools-api-1.9.22.pom": { "kotlin-build-tools-api-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-build-tools-api/1.9.22/kotlin-build-tools-api-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-build-tools-api/1.9.24/kotlin-build-tools-api-1.9.24.pom",
"hash": "sha256-DFZLu4fcXs32Q005buob886Xar8IgYCN0Wb6SbBGSfs=" "hash": "sha256-efIYZmDsHYeQhu4jEEeY2M1PthcsJ5xeVuAsqeVbxHU="
} }
}, },
"org.jetbrains.kotlin:kotlin-build-tools-impl:1.9.22": { "org.jetbrains.kotlin:kotlin-build-tools-impl:1.9.24": {
"kotlin-build-tools-impl-1.9.22.jar": { "kotlin-build-tools-impl-1.9.24.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-build-tools-impl/1.9.22/kotlin-build-tools-impl-1.9.22.jar", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-build-tools-impl/1.9.24/kotlin-build-tools-impl-1.9.24.jar",
"hash": "sha256-G0jW3gQqUl9jtVdROuEmbWmTSCJbAT+UDjLGPeJolCg=" "hash": "sha256-VPyCvEOOGGoMEGH55uYZEQuozUnFH6GOcFb726IpFhc="
}, },
"kotlin-build-tools-impl-1.9.22.pom": { "kotlin-build-tools-impl-1.9.24.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-build-tools-impl/1.9.22/kotlin-build-tools-impl-1.9.22.pom", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-build-tools-impl/1.9.24/kotlin-build-tools-impl-1.9.24.pom",
"hash": "sha256-tWM/E0m+lcdHRuHimiqm51LoneGrmmUjSS85j6aVWN0=" "hash": "sha256-WI+dA6B9qcDw3JZu6OWqjBEhsUf+1MdxsdwSTMnLONc="
} }
}, },
"org.jetbrains.kotlin:kotlin-compiler-embeddable:1.9.22": { "org.jetbrains.kotlin:kotlin-compiler-embeddable:1.9.24": {
"kotlin-compiler-embeddable-1.9.22.jar": { "kotlin-compiler-embeddable-1.9.24.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.9.22/kotlin-compiler-embeddable-1.9.22.jar", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.9.24/kotlin-compiler-embeddable-1.9.24.jar",
"hash": "sha256-K/6t7lmrGYjDNtvW5l2ZH3Zq4d2Gg/Km3tX6oCefDKA=" "hash": "sha256-5x/xnmsUGrhakyj9AQlBUxowJUMCa9QkTJWtwgjVAfY="
}, },
"kotlin-compiler-embeddable-1.9.22.pom": { "kotlin-compiler-embeddable-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.9.22/kotlin-compiler-embeddable-1.9.22.pom", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.9.24/kotlin-compiler-embeddable-1.9.24.pom",
"hash": "sha256-s9o0u29ClqzzoPRDRm8FBsbJnaXNliTW4LdFsiKHhOs=" "hash": "sha256-1w0fiFkkQ/R1eVFUVqTWwxBRztoK0RRGkjrK/kwMldE="
} }
}, },
"org.jetbrains.kotlin:kotlin-compiler-runner:1.9.22": { "org.jetbrains.kotlin:kotlin-compiler-runner:1.9.24": {
"kotlin-compiler-runner-1.9.22.jar": { "kotlin-compiler-runner-1.9.24.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-runner/1.9.22/kotlin-compiler-runner-1.9.22.jar", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-runner/1.9.24/kotlin-compiler-runner-1.9.24.jar",
"hash": "sha256-c+x1u5nr/6iySiSjuFPz9mCWvEapNRrw2sk967acFes=" "hash": "sha256-g4Q5dMH/0NNmbTxkk0Hb/TB32eFAZlVKakR7laMB3S0="
}, },
"kotlin-compiler-runner-1.9.22.pom": { "kotlin-compiler-runner-1.9.24.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-runner/1.9.22/kotlin-compiler-runner-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-runner/1.9.24/kotlin-compiler-runner-1.9.24.pom",
"hash": "sha256-pO6KZ8HW8lODjAAnKAvLgFCsDc3MrZdIlhOKaaAX6wE=" "hash": "sha256-wb508udfB+SamqaJA+DctogA0iRkBBi0hHfuQsvDWQQ="
} }
}, },
"org.jetbrains.kotlin:kotlin-daemon-client:1.9.22": { "org.jetbrains.kotlin:kotlin-daemon-client:1.9.24": {
"kotlin-daemon-client-1.9.22.jar": { "kotlin-daemon-client-1.9.24.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-client/1.9.22/kotlin-daemon-client-1.9.22.jar", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-client/1.9.24/kotlin-daemon-client-1.9.24.jar",
"hash": "sha256-XXPhgVsRZ+Sv4gjwCyp1wIC8WoEHhsqtuOFHh1k6k7k=" "hash": "sha256-WIqveo7Y55uL8+qLknj/Enii1ZKFpF4Jjxz8v7Dc080="
}, },
"kotlin-daemon-client-1.9.22.pom": { "kotlin-daemon-client-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-client/1.9.22/kotlin-daemon-client-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-client/1.9.24/kotlin-daemon-client-1.9.24.pom",
"hash": "sha256-YsRKZZ2lXbb7El4pKbmNUEow4fSvgU4I5JIUJqpST4o=" "hash": "sha256-tv4ne9GuP/zAzriOxmZZmHpc0TeaiXaDEvXe3x8uH+U="
} }
}, },
"org.jetbrains.kotlin:kotlin-daemon-embeddable:1.9.22": { "org.jetbrains.kotlin:kotlin-daemon-embeddable:1.9.24": {
"kotlin-daemon-embeddable-1.9.22.jar": { "kotlin-daemon-embeddable-1.9.24.jar": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.9.22/kotlin-daemon-embeddable-1.9.22.jar", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.9.24/kotlin-daemon-embeddable-1.9.24.jar",
"hash": "sha256-kqV4ExcUR9U0Rh+hP+N9yM07f4bYPpsfe7GwvjBUH4s=" "hash": "sha256-F3vIsqQHbcznh4rQ2P0HFjrzF44/qQ7mPU9zO7R7/ck="
}, },
"kotlin-daemon-embeddable-1.9.22.pom": { "kotlin-daemon-embeddable-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.9.22/kotlin-daemon-embeddable-1.9.22.pom", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.9.24/kotlin-daemon-embeddable-1.9.24.pom",
"hash": "sha256-9uo9z2v7Og0GmER8SKa88I2Oqs+D/JX+nUGBpeXjwrE=" "hash": "sha256-T7V/xqxyCVGzIkd0s7sqVFSelj0vTf3GhB6Ex77WKrE="
} }
}, },
"org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.22": { "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.24": {
"kotlin-gradle-plugin-1.9.22-gradle82.jar": { "kotlin-gradle-plugin-1.9.24-gradle82.jar": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin/1.9.22/kotlin-gradle-plugin-1.9.22-gradle82.jar", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin/1.9.24/kotlin-gradle-plugin-1.9.24-gradle82.jar",
"hash": "sha256-1OcY3V8wxrqTLZPM/FswFendPkQUOgUrh3Ao8frlQtw=" "hash": "sha256-6K7ZqBLmU2zu+z7VaPE0ZPoF8ka/0TaTONZDyDKUAks="
}, },
"kotlin-gradle-plugin-1.9.22.module": { "kotlin-gradle-plugin-1.9.24.module": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin/1.9.22/kotlin-gradle-plugin-1.9.22.module", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin/1.9.24/kotlin-gradle-plugin-1.9.24.module",
"hash": "sha256-pPRqwMq9jVzbaJ0tN9GdWFhPcIv59k/+TpgKL/dTS7U=" "hash": "sha256-txNZQoRrVH+xtZaGQXBGPC81+hW1qtkzX60P/YamE3s="
}, },
"kotlin-gradle-plugin-1.9.22.pom": { "kotlin-gradle-plugin-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin/1.9.22/kotlin-gradle-plugin-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin/1.9.24/kotlin-gradle-plugin-1.9.24.pom",
"hash": "sha256-A3750tSupA9JKdglE1g+STwOBRVuDaix1/Ujurhobyc=" "hash": "sha256-ilwTAHAhV//cHyV1hDZZbsVsM3Z8GqLouOskamWs9SM="
} }
}, },
"org.jetbrains.kotlin:kotlin-gradle-plugin-annotations:1.9.22": { "org.jetbrains.kotlin:kotlin-gradle-plugin-annotations:1.9.24": {
"kotlin-gradle-plugin-annotations-1.9.22.jar": { "kotlin-gradle-plugin-annotations-1.9.24.jar": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-annotations/1.9.22/kotlin-gradle-plugin-annotations-1.9.22.jar", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-annotations/1.9.24/kotlin-gradle-plugin-annotations-1.9.24.jar",
"hash": "sha256-lnaDy5jZkQFFYH+/W0VilbQ/Cq+Tsbunv2mS5zHLJOw=" "hash": "sha256-syBxajMCclSau65oGoD14P5YBLo5TQ8kW1s3f6JWNVk="
}, },
"kotlin-gradle-plugin-annotations-1.9.22.pom": { "kotlin-gradle-plugin-annotations-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-annotations/1.9.22/kotlin-gradle-plugin-annotations-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-annotations/1.9.24/kotlin-gradle-plugin-annotations-1.9.24.pom",
"hash": "sha256-Y7por+B4/3D3CPnpecaTxFv+iQQfeWQbC4H2tKEm7rs=" "hash": "sha256-fHb3hHzJ5bWOGoJbbqAZV7QoHpHmzXBcFmy+afvDtYs="
} }
}, },
"org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.9.22": { "org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.9.24": {
"kotlin-gradle-plugin-api-1.9.22-gradle82.jar": { "kotlin-gradle-plugin-api-1.9.24-gradle82.jar": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.9.22/kotlin-gradle-plugin-api-1.9.22-gradle82.jar", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.9.24/kotlin-gradle-plugin-api-1.9.24-gradle82.jar",
"hash": "sha256-7P9nVGBlxg4JX7k7P4i5uS7R7cN+P+u8b57TVCL6QSs=" "hash": "sha256-LV53JHoKf1klIL64gx6OPrl0m/OIhfgv+9Y8f/BRPhI="
}, },
"kotlin-gradle-plugin-api-1.9.22.jar": { "kotlin-gradle-plugin-api-1.9.24.jar": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.9.22/kotlin-gradle-plugin-api-1.9.22.jar", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.9.24/kotlin-gradle-plugin-api-1.9.24.jar",
"hash": "sha256-7P9nVGBlxg4JX7k7P4i5uS7R7cN+P+u8b57TVCL6QSs=" "hash": "sha256-LV53JHoKf1klIL64gx6OPrl0m/OIhfgv+9Y8f/BRPhI="
}, },
"kotlin-gradle-plugin-api-1.9.22.module": { "kotlin-gradle-plugin-api-1.9.24.module": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.9.22/kotlin-gradle-plugin-api-1.9.22.module", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.9.24/kotlin-gradle-plugin-api-1.9.24.module",
"hash": "sha256-H0SJxTBPmlEqVof/zAqvCTCvydcgUdOpBfrAcANi+3s=" "hash": "sha256-kB+s0LsPLdJ9XzvJDkQvJ3OrEuHOcgnT78HlhWNsfWQ="
}, },
"kotlin-gradle-plugin-api-1.9.22.pom": { "kotlin-gradle-plugin-api-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.9.22/kotlin-gradle-plugin-api-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.9.24/kotlin-gradle-plugin-api-1.9.24.pom",
"hash": "sha256-ZAFewaGutVCqGCjCQuIoODDFD2g2TkCDH+FYj9wEEfU=" "hash": "sha256-r9FlfZ0Vx2BxZ1InnZEdG73PjfTPXZYEUGHjCunBMX4="
} }
}, },
"org.jetbrains.kotlin:kotlin-gradle-plugin-idea:1.9.22": { "org.jetbrains.kotlin:kotlin-gradle-plugin-idea:1.9.24": {
"kotlin-gradle-plugin-idea-1.9.22.jar": { "kotlin-gradle-plugin-idea-1.9.24.jar": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.9.22/kotlin-gradle-plugin-idea-1.9.22.jar", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.9.24/kotlin-gradle-plugin-idea-1.9.24.jar",
"hash": "sha256-jRr4djLZUUjxIqn6CuKQPBnub6t9AeAX924NLJoCLCA=" "hash": "sha256-jRr4djLZUUjxIqn6CuKQPBnub6t9AeAX924NLJoCLCA="
}, },
"kotlin-gradle-plugin-idea-1.9.22.module": { "kotlin-gradle-plugin-idea-1.9.24.module": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.9.22/kotlin-gradle-plugin-idea-1.9.22.module", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.9.24/kotlin-gradle-plugin-idea-1.9.24.module",
"hash": "sha256-z+LCbjMPaAMsAD+lJMAx5aYPzo2Jn/8uQjFBKL60QCs=" "hash": "sha256-4Jx9wdImjqtl5EGtLjgWDzGHsNjAv5zxrUyF+nUjm6Q="
}, },
"kotlin-gradle-plugin-idea-1.9.22.pom": { "kotlin-gradle-plugin-idea-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.9.22/kotlin-gradle-plugin-idea-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.9.24/kotlin-gradle-plugin-idea-1.9.24.pom",
"hash": "sha256-3BSjKHVDun5QRs1OCVAtJ4hMqYfshwb1+xid54luOsw=" "hash": "sha256-aTnfzQ6JgI3AA25alaOPcb+EKF53bpEFIdVWJnp8sMc="
} }
}, },
"org.jetbrains.kotlin:kotlin-gradle-plugin-idea-proto:1.9.22": { "org.jetbrains.kotlin:kotlin-gradle-plugin-idea-proto:1.9.24": {
"kotlin-gradle-plugin-idea-proto-1.9.22.jar": { "kotlin-gradle-plugin-idea-proto-1.9.24.jar": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea-proto/1.9.22/kotlin-gradle-plugin-idea-proto-1.9.22.jar", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea-proto/1.9.24/kotlin-gradle-plugin-idea-proto-1.9.24.jar",
"hash": "sha256-9dgu5hlmotmK364Z8k1hcwIsFUBIls3yNjQANe5owPU=" "hash": "sha256-hR4BJ+5ixRDpf4UB6Q/V6yTQ15bHCcv5SvM5R0Fre/4="
}, },
"kotlin-gradle-plugin-idea-proto-1.9.22.pom": { "kotlin-gradle-plugin-idea-proto-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea-proto/1.9.22/kotlin-gradle-plugin-idea-proto-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea-proto/1.9.24/kotlin-gradle-plugin-idea-proto-1.9.24.pom",
"hash": "sha256-huMsqCkn2ogKHPNDpA7MIJgHXm/XInOzTVDfpUTzRjs=" "hash": "sha256-3gafD+sze0Nbc/GdKaISONBW5oegumvivczlmvqSa7Y="
} }
}, },
"org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.9.22": { "org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.9.24": {
"kotlin-gradle-plugin-model-1.9.22.jar": { "kotlin-gradle-plugin-model-1.9.24.jar": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.9.22/kotlin-gradle-plugin-model-1.9.22.jar", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.9.24/kotlin-gradle-plugin-model-1.9.24.jar",
"hash": "sha256-UQj61b4UmCXs46ABA8PCHPGv6VS7ZLhweJVyk511OMs=" "hash": "sha256-VbEQENUcmcMXybbvXpVJrUhXEhjN5hvYRIGMti0aPxk="
}, },
"kotlin-gradle-plugin-model-1.9.22.module": { "kotlin-gradle-plugin-model-1.9.24.module": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.9.22/kotlin-gradle-plugin-model-1.9.22.module", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.9.24/kotlin-gradle-plugin-model-1.9.24.module",
"hash": "sha256-L/MBPfK6epteiwBOhIF1DI0PqVOtAHoZbYXSY2cdvq4=" "hash": "sha256-cQXlShB2dqp9KAzFqUl0QX4qO1cD1w3WH8yr6wccSug="
}, },
"kotlin-gradle-plugin-model-1.9.22.pom": { "kotlin-gradle-plugin-model-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.9.22/kotlin-gradle-plugin-model-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.9.24/kotlin-gradle-plugin-model-1.9.24.pom",
"hash": "sha256-gfUmlHml2X7oeSpITIMr495DgggSZxlhUAHKyI5C9qg=" "hash": "sha256-rquP4uqM+lwumZi1/nU4MaeYfCx4Q6U1MjYqB/pvABg="
} }
}, },
"org.jetbrains.kotlin:kotlin-gradle-plugins-bom:1.9.22": { "org.jetbrains.kotlin:kotlin-gradle-plugins-bom:1.9.24": {
"kotlin-gradle-plugins-bom-1.9.22.module": { "kotlin-gradle-plugins-bom-1.9.24.module": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugins-bom/1.9.22/kotlin-gradle-plugins-bom-1.9.22.module", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugins-bom/1.9.24/kotlin-gradle-plugins-bom-1.9.24.module",
"hash": "sha256-Qj401h0iCxoN3BgUCGqM6rTa2ed5ArDOjLRyG789xu0=" "hash": "sha256-BEh8cNHIzCkBwDdNgarX+k/Rp5NeJa200LH69WkKzNs="
}, },
"kotlin-gradle-plugins-bom-1.9.22.pom": { "kotlin-gradle-plugins-bom-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugins-bom/1.9.22/kotlin-gradle-plugins-bom-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-gradle-plugins-bom/1.9.24/kotlin-gradle-plugins-bom-1.9.24.pom",
"hash": "sha256-da2/XHjOJHwiuvNijQs/8c9+19N9YB66cwTXerdb3Z8=" "hash": "sha256-wqVTvkQFNLjTMOV69hNjc1WLXgIPppzPsDsuWDx1nAA="
} }
}, },
"org.jetbrains.kotlin:kotlin-klib-commonizer-api:1.9.22": { "org.jetbrains.kotlin:kotlin-klib-commonizer-api:1.9.24": {
"kotlin-klib-commonizer-api-1.9.22.jar": { "kotlin-klib-commonizer-api-1.9.24.jar": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.9.22/kotlin-klib-commonizer-api-1.9.22.jar", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.9.24/kotlin-klib-commonizer-api-1.9.24.jar",
"hash": "sha256-jC9lQpwYLi5KLgnLkQ5iuW227tKFWUuPga+CO35ZROI=" "hash": "sha256-U791bL22Uj3LTA16syrLZBR5bBz0nOQxvkC3DMV9tUk="
}, },
"kotlin-klib-commonizer-api-1.9.22.pom": { "kotlin-klib-commonizer-api-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.9.22/kotlin-klib-commonizer-api-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.9.24/kotlin-klib-commonizer-api-1.9.24.pom",
"hash": "sha256-EMrJcNMAo0icM/CzBBVv8DLZWVm+WqrDuIAoKtWGIv4=" "hash": "sha256-6pO4z4DdKXdKf7GEeclxH7uWPqhqwjq2FOepQAUsZ34="
} }
}, },
"org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:1.9.22": { "org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:1.9.24": {
"kotlin-klib-commonizer-embeddable-1.9.22.jar": { "kotlin-klib-commonizer-embeddable-1.9.24.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-klib-commonizer-embeddable/1.9.22/kotlin-klib-commonizer-embeddable-1.9.22.jar", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-klib-commonizer-embeddable/1.9.24/kotlin-klib-commonizer-embeddable-1.9.24.jar",
"hash": "sha256-c/50PnTSEoPTg9C6voX9CMRCr8GnvYgIL42gUQ0FPUs=" "hash": "sha256-AUyBXNeOK4yub4JeHOpPMd6v4HEBOh0G/jZXVzTDA6E="
}, },
"kotlin-klib-commonizer-embeddable-1.9.22.pom": { "kotlin-klib-commonizer-embeddable-1.9.24.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-klib-commonizer-embeddable/1.9.22/kotlin-klib-commonizer-embeddable-1.9.22.pom", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-klib-commonizer-embeddable/1.9.24/kotlin-klib-commonizer-embeddable-1.9.24.pom",
"hash": "sha256-dxghItppe2YqSRPX3Z/mu68ATOhH/YZ9oj6v8MTIJEs=" "hash": "sha256-yshuQs6nFQwXJJW69k1hWar/vCjFm1+433K+p1iL9Rw="
} }
}, },
"org.jetbrains.kotlin:kotlin-native-utils:1.9.22": { "org.jetbrains.kotlin:kotlin-native-utils:1.9.24": {
"kotlin-native-utils-1.9.22.jar": { "kotlin-native-utils-1.9.24.jar": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-native-utils/1.9.22/kotlin-native-utils-1.9.22.jar", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-native-utils/1.9.24/kotlin-native-utils-1.9.24.jar",
"hash": "sha256-eGwSfdVTXbLDmuWXzQsMrZ6RS4PiNvHbAlEjXMnGUqw=" "hash": "sha256-I1WvMJo7FgeymmF02Fe05umxs2EH1sHvu8PMSbpDRQw="
}, },
"kotlin-native-utils-1.9.22.pom": { "kotlin-native-utils-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-native-utils/1.9.22/kotlin-native-utils-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-native-utils/1.9.24/kotlin-native-utils-1.9.24.pom",
"hash": "sha256-EcUUwF7qOuno4Wq0l5bxEd9DxzSCMeNfr0xCjMT3Q+o=" "hash": "sha256-uvA25RxRge8Q8wVRXRnfawKWsLcIS0g9I4oImN630i0="
} }
}, },
"org.jetbrains.kotlin:kotlin-project-model:1.9.22": { "org.jetbrains.kotlin:kotlin-project-model:1.9.24": {
"kotlin-project-model-1.9.22.jar": { "kotlin-project-model-1.9.24.jar": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-project-model/1.9.22/kotlin-project-model-1.9.22.jar", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-project-model/1.9.24/kotlin-project-model-1.9.24.jar",
"hash": "sha256-zBHVwLGQnFsKCP0l7w51T/0r9Wyu9mX7eFEiI15UKhg=" "hash": "sha256-Nri/x5EqvuVIWSxcI5keVRQODS17OhqTTdPOj6Q0+N0="
}, },
"kotlin-project-model-1.9.22.pom": { "kotlin-project-model-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-project-model/1.9.22/kotlin-project-model-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-project-model/1.9.24/kotlin-project-model-1.9.24.pom",
"hash": "sha256-659KFngb/ADM7IAw++XuIo5vKydxxQwmezIY/rAGW0A=" "hash": "sha256-sF4O4QAsGO3t626JrwfjvheFB9sT2hutbs52vmDz7es="
}
},
"org.jetbrains.kotlin:kotlin-reflect:1.9.24": {
"kotlin-reflect-1.9.24.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.9.24/kotlin-reflect-1.9.24.jar",
"hash": "sha256-plFmRFu4XvgWzeEnJ5/gAX0rfMQ5s7lyOQ4bc21k6Uw="
},
"kotlin-reflect-1.9.24.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.9.24/kotlin-reflect-1.9.24.pom",
"hash": "sha256-CghcMAUb1tSrdlrVoMUXnEE7NfdBjyiDFy+9m6GrzMk="
} }
}, },
"org.jetbrains.kotlin:kotlin-reflect:1.9.23": { "org.jetbrains.kotlin:kotlin-reflect:1.9.23": {
@@ -1551,16 +1481,6 @@
"hash": "sha256-WXD72CdKWAyk6I/nhkeMR8i5ufo3TFsK3ekyhFYiX2o=" "hash": "sha256-WXD72CdKWAyk6I/nhkeMR8i5ufo3TFsK3ekyhFYiX2o="
} }
}, },
"org.jetbrains.kotlin:kotlin-reflect:1.9.22": {
"kotlin-reflect-1.9.22.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.9.22/kotlin-reflect-1.9.22.jar",
"hash": "sha256-d/MRyhOEgR1Rn9o4n8sSaL2qBY1gUEbg7edsA7DfPpc="
},
"kotlin-reflect-1.9.22.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.9.22/kotlin-reflect-1.9.22.pom",
"hash": "sha256-xxLjWN97kxi2j1RjlxsIhnODf8DKQoXRw4LIEC7da18="
}
},
"org.jetbrains.kotlin:kotlin-reflect:1.8.22": { "org.jetbrains.kotlin:kotlin-reflect:1.8.22": {
"kotlin-reflect-1.8.22.jar": { "kotlin-reflect-1.8.22.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.8.22/kotlin-reflect-1.8.22.jar", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.8.22/kotlin-reflect-1.8.22.jar",
@@ -1581,124 +1501,106 @@
"hash": "sha256-V5BVJCdKAK4CiqzMJyg/a8WSWpNKBGwcxdBsjuTW1ak=" "hash": "sha256-V5BVJCdKAK4CiqzMJyg/a8WSWpNKBGwcxdBsjuTW1ak="
} }
}, },
"org.jetbrains.kotlin:kotlin-script-runtime:1.9.22": { "org.jetbrains.kotlin:kotlin-script-runtime:1.9.24": {
"kotlin-script-runtime-1.9.22.jar": { "kotlin-script-runtime-1.9.24.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-script-runtime/1.9.22/kotlin-script-runtime-1.9.22.jar", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-script-runtime/1.9.24/kotlin-script-runtime-1.9.24.jar",
"hash": "sha256-uAZwV59/ktRz2NWDTwsST3dVxFmP6UskQYOwKDSDRXQ=" "hash": "sha256-MUx9MI/nUGVDZbrGFEeAYTyRac89nh2vurkc+AvcNXw="
}, },
"kotlin-script-runtime-1.9.22.pom": { "kotlin-script-runtime-1.9.24.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-script-runtime/1.9.22/kotlin-script-runtime-1.9.22.pom", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-script-runtime/1.9.24/kotlin-script-runtime-1.9.24.pom",
"hash": "sha256-/ra0ns9pEG1MEoXnH5ob2noSfO9oMC4+n9yCmKTjR5U=" "hash": "sha256-mGDF58qg5AlxmVCQEtoD01GX/teewKkKUOKPjeh1QE0="
} }
}, },
"org.jetbrains.kotlin:kotlin-scripting-common:1.9.22": { "org.jetbrains.kotlin:kotlin-scripting-common:1.9.24": {
"kotlin-scripting-common-1.9.22.jar": { "kotlin-scripting-common-1.9.24.jar": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-common/1.9.22/kotlin-scripting-common-1.9.22.jar", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-common/1.9.24/kotlin-scripting-common-1.9.24.jar",
"hash": "sha256-+lAMvwNJQ++BJvPT3GWvCf+Z3//kTFCZtPwu1b8vXcc=" "hash": "sha256-KqeY6XgokBDYByTdGdn+GQtSQkFIEQT89RjAO8OdTks="
}, },
"kotlin-scripting-common-1.9.22.pom": { "kotlin-scripting-common-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-common/1.9.22/kotlin-scripting-common-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-common/1.9.24/kotlin-scripting-common-1.9.24.pom",
"hash": "sha256-ROURI7DCfm/ZM/wma00Nrw8GhKYq7Z/mhC6Noz8qKz8=" "hash": "sha256-S9rpUqslCWFRsfqERCooGupzwW0dTNVdigLDccqJusQ="
} }
}, },
"org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.9.22": { "org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.9.24": {
"kotlin-scripting-compiler-embeddable-1.9.22.jar": { "kotlin-scripting-compiler-embeddable-1.9.24.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.9.22/kotlin-scripting-compiler-embeddable-1.9.22.jar", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.9.24/kotlin-scripting-compiler-embeddable-1.9.24.jar",
"hash": "sha256-Ij/shIMCNEmc1MeiPqHJLroSfEGzXZux1LYdJBVa6zU=" "hash": "sha256-02gR+1yZeXaEH/PQqxnGt96RkomeQIK6Hz/7oH6UBfQ="
}, },
"kotlin-scripting-compiler-embeddable-1.9.22.pom": { "kotlin-scripting-compiler-embeddable-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.9.22/kotlin-scripting-compiler-embeddable-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.9.24/kotlin-scripting-compiler-embeddable-1.9.24.pom",
"hash": "sha256-wWCPP7yyqfdSPq0zWZwurc5MgSFhqeBmufSwBa97Qxw=" "hash": "sha256-FUgOkd8v/sfFfOHgpfFBBltFIrbbyJsv2yk9xsVwwMU="
} }
}, },
"org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.9.22": { "org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.9.24": {
"kotlin-scripting-compiler-impl-embeddable-1.9.22.jar": { "kotlin-scripting-compiler-impl-embeddable-1.9.24.jar": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.9.22/kotlin-scripting-compiler-impl-embeddable-1.9.22.jar", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.9.24/kotlin-scripting-compiler-impl-embeddable-1.9.24.jar",
"hash": "sha256-OJkYFqKH/3YkHxp35/ERZIHU6To9tjJZplfd4g5tD2U=" "hash": "sha256-i/2A2RNqKjJhALC3O/saG7NX7d+uDYEiDkYSa4im7no="
}, },
"kotlin-scripting-compiler-impl-embeddable-1.9.22.pom": { "kotlin-scripting-compiler-impl-embeddable-1.9.24.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.9.22/kotlin-scripting-compiler-impl-embeddable-1.9.22.pom", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.9.24/kotlin-scripting-compiler-impl-embeddable-1.9.24.pom",
"hash": "sha256-gmccM6lXsuKoINZqaSwvzmPjvwR/HLJeb7A5HF3c8uc=" "hash": "sha256-Sg6yUXF8Sih6ZBfp/QRBZ4xJatxnAdhasPFi8W0s+4c="
} }
}, },
"org.jetbrains.kotlin:kotlin-scripting-jvm:1.9.22": { "org.jetbrains.kotlin:kotlin-scripting-jvm:1.9.24": {
"kotlin-scripting-jvm-1.9.22.jar": { "kotlin-scripting-jvm-1.9.24.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.9.22/kotlin-scripting-jvm-1.9.22.jar", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.9.24/kotlin-scripting-jvm-1.9.24.jar",
"hash": "sha256-jRJ9dvz6BRfDbB6g4ijs4D1aRoJkKgH2R5prvccxKik=" "hash": "sha256-G9aQBgqUhDl3N0pFds2J10nk7srx+3pYA2/rOuVRxKw="
}, },
"kotlin-scripting-jvm-1.9.22.pom": { "kotlin-scripting-jvm-1.9.24.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.9.22/kotlin-scripting-jvm-1.9.22.pom", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.9.24/kotlin-scripting-jvm-1.9.24.pom",
"hash": "sha256-cBJS6huo/4f8M0dqYePVxtnS3aQbqpiZTdaYDuE/vG0=" "hash": "sha256-kkM+M+MLpFvMS/hKxUsX0p8Dlkp2BwYW1sZS3WxhySU="
} }
}, },
"org.jetbrains.kotlin:kotlin-serialization:1.9.22": { "org.jetbrains.kotlin:kotlin-serialization:1.9.24": {
"kotlin-serialization-1.9.22-gradle82.jar": { "kotlin-serialization-1.9.24-gradle82.jar": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-serialization/1.9.22/kotlin-serialization-1.9.22-gradle82.jar", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-serialization/1.9.24/kotlin-serialization-1.9.24-gradle82.jar",
"hash": "sha256-AcrgEEPdT3sLAttWbZPHVoiwlsNAkJ9o0OSVcqvF6VQ=" "hash": "sha256-qwl/Ug33fXOXhQfsR6/B2K9ME0tn5hCrfcLLzYrFIFg="
}, },
"kotlin-serialization-1.9.22.module": { "kotlin-serialization-1.9.24.module": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-serialization/1.9.22/kotlin-serialization-1.9.22.module", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-serialization/1.9.24/kotlin-serialization-1.9.24.module",
"hash": "sha256-s3cuUZFg/is2t9G6MkGQYU27lLFZzmBk9M1z+RhhWiI=" "hash": "sha256-aRNY++5uyvcPyLLR8ic1q21RAErJHEh8Jbdm2xPD74k="
}, },
"kotlin-serialization-1.9.22.pom": { "kotlin-serialization-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-serialization/1.9.22/kotlin-serialization-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-serialization/1.9.24/kotlin-serialization-1.9.24.pom",
"hash": "sha256-D9yUsPEx2Ct3RpAEB0r0f/yntGfVeIn762oVSWg+rL0=" "hash": "sha256-5JgomGgooBL/9+I+cSUCASVSzCtmOdx3HgsX2VINhJ0="
} }
}, },
"org.jetbrains.kotlin:kotlin-serialization-compiler-plugin-embeddable:1.9.22": { "org.jetbrains.kotlin:kotlin-serialization-compiler-plugin-embeddable:1.9.24": {
"kotlin-serialization-compiler-plugin-embeddable-1.9.22.jar": { "kotlin-serialization-compiler-plugin-embeddable-1.9.24.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-serialization-compiler-plugin-embeddable/1.9.22/kotlin-serialization-compiler-plugin-embeddable-1.9.22.jar", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-serialization-compiler-plugin-embeddable/1.9.24/kotlin-serialization-compiler-plugin-embeddable-1.9.24.jar",
"hash": "sha256-OFR9AAsWYbFLkkZxz7F6tSAL64NOOj2kJ37gkGLppQA=" "hash": "sha256-T/XIE76vaHjvBxFIZvU4keMdlscr+XWMvG81CmxNNs0="
}, },
"kotlin-serialization-compiler-plugin-embeddable-1.9.22.pom": { "kotlin-serialization-compiler-plugin-embeddable-1.9.24.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-serialization-compiler-plugin-embeddable/1.9.22/kotlin-serialization-compiler-plugin-embeddable-1.9.22.pom", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-serialization-compiler-plugin-embeddable/1.9.24/kotlin-serialization-compiler-plugin-embeddable-1.9.24.pom",
"hash": "sha256-i8LheiTLbQ4CMzLkjKq5e3P+MyuSdVWhGjAsb1xcPGQ=" "hash": "sha256-GWjfZLq2HzC6UvTrMQ0tzFl1IQGbsUL72ZPw5VWk3+k="
} }
}, },
"org.jetbrains.kotlin:kotlin-stdlib:1.9.23": { "org.jetbrains.kotlin:kotlin-stdlib:1.9.24": {
"kotlin-stdlib-1.9.23-all.jar": { "kotlin-stdlib-1.9.24-all.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.23/kotlin-stdlib-1.9.23-all.jar", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.24/kotlin-stdlib-1.9.24-all.jar",
"hash": "sha256-zsOLwzAucqiq+c3kNrWpBx7gMx4q0F6E2LuJczTX6dQ=" "hash": "sha256-zsOLwzAucqiq+c3kNrWpBx7gMx4q0F6E2LuJczTX6dQ="
}, },
"kotlin-stdlib-1.9.23.jar": { "kotlin-stdlib-1.9.24.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.23/kotlin-stdlib-1.9.23.jar", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.24/kotlin-stdlib-1.9.24.jar",
"hash": "sha256-iRDMI4gH2G71UMsfCxDdXtQLNaTsGlJSX3YK7ehOrTc=" "hash": "sha256-hYuQJpbanPWFq52Y/8HCcSJpgoNU3+kQfjcRsISjZGg="
}, },
"kotlin-stdlib-1.9.23.module": { "kotlin-stdlib-1.9.24.module": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.23/kotlin-stdlib-1.9.23.module", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.24/kotlin-stdlib-1.9.24.module",
"hash": "sha256-UZUZOzfc2touHAqw1RLEIrKtdq81V4Q6G5w0gPTnHQ4=" "hash": "sha256-8uKmVztbUmXEEtXFgfv46gDGKxC5yS1WdMnpfy8zNbM="
}, },
"kotlin-stdlib-1.9.23.pom": { "kotlin-stdlib-1.9.24.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.23/kotlin-stdlib-1.9.23.pom", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.24/kotlin-stdlib-1.9.24.pom",
"hash": "sha256-wm0n8mcQrUDiPu2f/gpkuFkejBPSI8ypDFk+5j87KKs=" "hash": "sha256-uc6tTCIt7pDHT28BPTFqnlD4EaApMxPDNRrssvfM7V8="
} }
}, },
"org.jetbrains.kotlin:kotlin-stdlib:1.9.22": { "org.jetbrains.kotlin:kotlin-stdlib-common:1.9.24": {
"kotlin-stdlib-1.9.22-all.jar": { "kotlin-stdlib-common-1.9.24.module": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.22/kotlin-stdlib-1.9.22-all.jar", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.9.24/kotlin-stdlib-common-1.9.24.module",
"hash": "sha256-zsOLwzAucqiq+c3kNrWpBx7gMx4q0F6E2LuJczTX6dQ=" "hash": "sha256-6Y6oxE+zaCDQG7iwAxaOI6IhtAHLQyVtcjo/C3fWFsI="
}, },
"kotlin-stdlib-1.9.22.jar": { "kotlin-stdlib-common-1.9.24.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.22/kotlin-stdlib-1.9.22.jar", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.9.24/kotlin-stdlib-common-1.9.24.pom",
"hash": "sha256-ar4UbCeGQTi4dMzM/l9TTj65I8maG3tdRUlO5WlPPgo=" "hash": "sha256-XZfiDNWGLoR6aYF1uTno3Fxr11vtmZ1vPU6ghIESFsA="
},
"kotlin-stdlib-1.9.22.module": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.22/kotlin-stdlib-1.9.22.module",
"hash": "sha256-9IIxS1B5wUVfb7DUJXp0XRAcYSTOlhUiuob53JCQHkc="
},
"kotlin-stdlib-1.9.22.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.22/kotlin-stdlib-1.9.22.pom",
"hash": "sha256-zOLxUoXsgHijd0a1cwigVAQt1cwlQgxD9zt4V8JGjwM="
}
},
"org.jetbrains.kotlin:kotlin-stdlib-common:1.9.23": {
"kotlin-stdlib-common-1.9.23.module": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.9.23/kotlin-stdlib-common-1.9.23.module",
"hash": "sha256-hjnwBfqZd67wjDL8jnonedoi7iYkZNcnMpiq/Ug3Fc0="
},
"kotlin-stdlib-common-1.9.23.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.9.23/kotlin-stdlib-common-1.9.23.pom",
"hash": "sha256-OuBxRYdw47aGCafTGet5emeJ9fBAyqQUQJgJmGhb5PY="
} }
}, },
"org.jetbrains.kotlin:kotlin-stdlib-common:1.9.22": { "org.jetbrains.kotlin:kotlin-stdlib-common:1.9.22": {
@@ -1711,24 +1613,14 @@
"hash": "sha256-10k21oh1ZK63EOhCmLVCB/U+m88jpSrSv6IsIIZ3V2c=" "hash": "sha256-10k21oh1ZK63EOhCmLVCB/U+m88jpSrSv6IsIIZ3V2c="
} }
}, },
"org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.22": { "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.24": {
"kotlin-stdlib-jdk7-1.9.22.jar": { "kotlin-stdlib-jdk7-1.9.24.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.9.22/kotlin-stdlib-jdk7-1.9.22.jar", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.9.24/kotlin-stdlib-jdk7-1.9.24.jar",
"hash": "sha256-+R8kz606dWaIo1Ep5fM1SA0OtAjxVooX9wfCifh2m90=" "hash": "sha256-tmmbhQugeJ8ukEJ5zYvce+qRMP/RV826AB/HQl2KR7c="
}, },
"kotlin-stdlib-jdk7-1.9.22.pom": { "kotlin-stdlib-jdk7-1.9.24.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.9.22/kotlin-stdlib-jdk7-1.9.22.pom", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.9.24/kotlin-stdlib-jdk7-1.9.24.pom",
"hash": "sha256-SHnKgQKDPIraP0bHep/6+uGXDK/AvGIfUSAbatl0zp0=" "hash": "sha256-RYapN9W8vDqzBCwECaHHKWFLy6PHpylvJS1ibuNzh9Q="
}
},
"org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.21": {
"kotlin-stdlib-jdk7-1.9.21.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.9.21/kotlin-stdlib-jdk7-1.9.21.jar",
"hash": "sha256-v+IfQkbIvKNQsYQEBv+803awXto36ypksBHeGMLKeBg="
},
"kotlin-stdlib-jdk7-1.9.21.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.9.21/kotlin-stdlib-jdk7-1.9.21.pom",
"hash": "sha256-AVFiDhh0XvJ2ECNw/GdHBPcN821kgsxBmh5S263Cg2I="
} }
}, },
"org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.22": { "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.22": {
@@ -1741,24 +1633,14 @@
"hash": "sha256-T5WKqZPVmE+PXr7UFGVipfOp9pW2BJyfKHOBN5ytqzM=" "hash": "sha256-T5WKqZPVmE+PXr7UFGVipfOp9pW2BJyfKHOBN5ytqzM="
} }
}, },
"org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.22": { "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.24": {
"kotlin-stdlib-jdk8-1.9.22.jar": { "kotlin-stdlib-jdk8-1.9.24.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.9.22/kotlin-stdlib-jdk8-1.9.22.jar", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.9.24/kotlin-stdlib-jdk8-1.9.24.jar",
"hash": "sha256-RwRsPtwy/g2xo2v+PTgilYu1vkQRxbqA866JWj7CcpE=" "hash": "sha256-W1u/s+EYS14TMXw9QiN/okrdRDsud4GWHuozTbE2rbE="
}, },
"kotlin-stdlib-jdk8-1.9.22.pom": { "kotlin-stdlib-jdk8-1.9.24.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.9.22/kotlin-stdlib-jdk8-1.9.22.pom", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.9.24/kotlin-stdlib-jdk8-1.9.24.pom",
"hash": "sha256-yUBIJZxtAAdXi6r+tx74/3ut6wjy1ZQ3/DllHg+396s=" "hash": "sha256-BuBt70n5aq9uXD7EKDauWdbi2mJUcAkUKBZ1Z53J8qU="
}
},
"org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.21": {
"kotlin-stdlib-jdk8-1.9.21.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.9.21/kotlin-stdlib-jdk8-1.9.21.jar",
"hash": "sha256-BwLWS6qpDlxW5GdzeCTJvjreHlFWJHPBQ60DWByVUSc="
},
"kotlin-stdlib-jdk8-1.9.21.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.9.21/kotlin-stdlib-jdk8-1.9.21.pom",
"hash": "sha256-J79Q6ETwZc0emFT8m8K9pRIrh4ZOoDBL1pW7En0AMvQ="
} }
}, },
"org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.22": { "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.22": {
@@ -1771,46 +1653,46 @@
"hash": "sha256-ko8hhyF0djE8uBbUgHC8dlSqO5pa6B0/xfjCecyPjZ4=" "hash": "sha256-ko8hhyF0djE8uBbUgHC8dlSqO5pa6B0/xfjCecyPjZ4="
} }
}, },
"org.jetbrains.kotlin:kotlin-tooling-core:1.9.22": { "org.jetbrains.kotlin:kotlin-tooling-core:1.9.24": {
"kotlin-tooling-core-1.9.22.jar": { "kotlin-tooling-core-1.9.24.jar": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-tooling-core/1.9.22/kotlin-tooling-core-1.9.22.jar", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-tooling-core/1.9.24/kotlin-tooling-core-1.9.24.jar",
"hash": "sha256-iTjrl+NjINqj5vsqYP0qBbIy/0pVcXPFAZ8EW4gy2fQ=" "hash": "sha256-iTjrl+NjINqj5vsqYP0qBbIy/0pVcXPFAZ8EW4gy2fQ="
}, },
"kotlin-tooling-core-1.9.22.pom": { "kotlin-tooling-core-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-tooling-core/1.9.22/kotlin-tooling-core-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-tooling-core/1.9.24/kotlin-tooling-core-1.9.24.pom",
"hash": "sha256-FPx/NcY15fzRvqU3q0+kQxLoQyUtUzNRnjaxJeoImyE=" "hash": "sha256-dbytE+kWgPzwEsjuGqGqxxn1m2IbOUyj/DLGJf+YclY="
} }
}, },
"org.jetbrains.kotlin:kotlin-util-io:1.9.22": { "org.jetbrains.kotlin:kotlin-util-io:1.9.24": {
"kotlin-util-io-1.9.22.jar": { "kotlin-util-io-1.9.24.jar": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-io/1.9.22/kotlin-util-io-1.9.22.jar", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-io/1.9.24/kotlin-util-io-1.9.24.jar",
"hash": "sha256-9telhJGjeLCDrRvq1IikheEdFgsx52wYwa1SDx0o9Gs=" "hash": "sha256-u0z0H/UG5Q+bLDQiBkmIFupO3f6ImYqQtotDlLT6xfo="
}, },
"kotlin-util-io-1.9.22.pom": { "kotlin-util-io-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-io/1.9.22/kotlin-util-io-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-io/1.9.24/kotlin-util-io-1.9.24.pom",
"hash": "sha256-ZP1qINbsBAE7ttdWJ/ZYC7c2QdlIkJ1cFmTi53MQbe4=" "hash": "sha256-82VnN3kyTzMtOTkMeAd1h4BNEeznKv5K7uMlOtZTPFE="
} }
}, },
"org.jetbrains.kotlin:kotlin-util-klib:1.9.22": { "org.jetbrains.kotlin:kotlin-util-klib:1.9.24": {
"kotlin-util-klib-1.9.22.jar": { "kotlin-util-klib-1.9.24.jar": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-klib/1.9.22/kotlin-util-klib-1.9.22.jar", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-klib/1.9.24/kotlin-util-klib-1.9.24.jar",
"hash": "sha256-pnnuL1EPOrkmkYGN5etbCQLobYjJdnTn20TcTyJSxfk=" "hash": "sha256-4NqKfwZIV8BIOmVyfRYtPtV84m1+R3ix8ADg0MDck3E="
}, },
"kotlin-util-klib-1.9.22.pom": { "kotlin-util-klib-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-klib/1.9.22/kotlin-util-klib-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-util-klib/1.9.24/kotlin-util-klib-1.9.24.pom",
"hash": "sha256-Dep9//Cit0CIrJlwQ8vCQINdK/9Zs5/MiwysbqPrNpc=" "hash": "sha256-krQjr9XnKbsRT3G1ip4DhF3+K9pWJFTrvbg8nYOyMHE="
} }
}, },
"org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.9.22": { "org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.9.24": {
"org.jetbrains.kotlin.jvm.gradle.plugin-1.9.22.pom": { "org.jetbrains.kotlin.jvm.gradle.plugin-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.9.22/org.jetbrains.kotlin.jvm.gradle.plugin-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.9.24/org.jetbrains.kotlin.jvm.gradle.plugin-1.9.24.pom",
"hash": "sha256-HLTsuTPJGbL7/XZe/KX+SQeghxLoyZQsM6IIsrFpsYw=" "hash": "sha256-7v934tgCArrgxdMiTdws8lklMcyyuJL2uFSyMd+fEBU="
} }
}, },
"org.jetbrains.kotlin.plugin.serialization:org.jetbrains.kotlin.plugin.serialization.gradle.plugin:1.9.22": { "org.jetbrains.kotlin.plugin.serialization:org.jetbrains.kotlin.plugin.serialization.gradle.plugin:1.9.24": {
"org.jetbrains.kotlin.plugin.serialization.gradle.plugin-1.9.22.pom": { "org.jetbrains.kotlin.plugin.serialization.gradle.plugin-1.9.24.pom": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/plugin/serialization/org.jetbrains.kotlin.plugin.serialization.gradle.plugin/1.9.22/org.jetbrains.kotlin.plugin.serialization.gradle.plugin-1.9.22.pom", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlin/plugin/serialization/org.jetbrains.kotlin.plugin.serialization.gradle.plugin/1.9.24/org.jetbrains.kotlin.plugin.serialization.gradle.plugin-1.9.24.pom",
"hash": "sha256-+9WDi7OolDJys/EfhJrIlDeJL9MJstA012QjjEVPoyI=" "hash": "sha256-4VQlt07TxI1q7g8h3u9MQ5npbV4lZ3vxVZVNOBYRZII="
} }
}, },
"org.jetbrains.kotlinx:atomicfu:0.23.1": { "org.jetbrains.kotlinx:atomicfu:0.23.1": {
@@ -1859,20 +1741,6 @@
"hash": "sha256-+IkY2/qHh8TRcasCVToUrR3viqmwxcLCDMmUVdMkHiI=" "hash": "sha256-+IkY2/qHh8TRcasCVToUrR3viqmwxcLCDMmUVdMkHiI="
} }
}, },
"org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0": {
"kotlinx-coroutines-core-1.8.0.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core/1.8.0/kotlinx-coroutines-core-1.8.0.jar",
"hash": "sha256-IKpDS2qTDqZtLmGwDe764J/qPTL5ZA0uDCcTEogOCt0="
},
"kotlinx-coroutines-core-1.8.0.module": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core/1.8.0/kotlinx-coroutines-core-1.8.0.module",
"hash": "sha256-FE7s1TZd4+MNe0YibAWAUeOZVbXBieMfpMfP+5nWILo="
},
"kotlinx-coroutines-core-1.8.0.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core/1.8.0/kotlinx-coroutines-core-1.8.0.pom",
"hash": "sha256-yglaS/iLR0+trOgzLBCXC3nLgBu/XfBHo5Ov4Ql28yE="
}
},
"org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.8.1": { "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.8.1": {
"kotlinx-coroutines-core-jvm-1.8.1.jar": { "kotlinx-coroutines-core-jvm-1.8.1.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.8.1/kotlinx-coroutines-core-jvm-1.8.1.jar", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.8.1/kotlinx-coroutines-core-jvm-1.8.1.jar",
@@ -1887,20 +1755,6 @@
"hash": "sha256-R8alCxQVHo+vfzUKlSNcN9EqvDi/sFW2aJdCkxctryw=" "hash": "sha256-R8alCxQVHo+vfzUKlSNcN9EqvDi/sFW2aJdCkxctryw="
} }
}, },
"org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.8.0": {
"kotlinx-coroutines-core-jvm-1.8.0.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.8.0/kotlinx-coroutines-core-jvm-1.8.0.jar",
"hash": "sha256-mGCQahk3SQv187BtLw4Q70UeZblbJp8i2vaKPR9QZcU="
},
"kotlinx-coroutines-core-jvm-1.8.0.module": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.8.0/kotlinx-coroutines-core-jvm-1.8.0.module",
"hash": "sha256-/2oi2kAECTh1HbCuIRd+dlF9vxJqdnlvVCZye/dsEig="
},
"kotlinx-coroutines-core-jvm-1.8.0.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.8.0/kotlinx-coroutines-core-jvm-1.8.0.pom",
"hash": "sha256-pWM6vVNGfOuRYi2B8umCCAh3FF4LduG3V4hxVDSIXQs="
}
},
"org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.0": { "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.0": {
"kotlinx-coroutines-core-jvm-1.5.0.jar": { "kotlinx-coroutines-core-jvm-1.5.0.jar": {
"url": "https://plugins.gradle.org/m2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.5.0/kotlinx-coroutines-core-jvm-1.5.0.jar", "url": "https://plugins.gradle.org/m2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.5.0/kotlinx-coroutines-core-jvm-1.5.0.jar",
@@ -1929,20 +1783,6 @@
"hash": "sha256-x9+Ci/O0+ofumYH7ATaN1NwHmV0XzLqPpmEhcTwF69Q=" "hash": "sha256-x9+Ci/O0+ofumYH7ATaN1NwHmV0XzLqPpmEhcTwF69Q="
} }
}, },
"org.jetbrains.kotlinx:kotlinx-coroutines-debug:1.8.0": {
"kotlinx-coroutines-debug-1.8.0.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-debug/1.8.0/kotlinx-coroutines-debug-1.8.0.jar",
"hash": "sha256-Zy1UU0UXCoyrgoeygZRL55DWdUWXK+vdVKor9MhsxT8="
},
"kotlinx-coroutines-debug-1.8.0.module": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-debug/1.8.0/kotlinx-coroutines-debug-1.8.0.module",
"hash": "sha256-piquUrrd+ncw5Wey6kHzYOoQqbN8FiJDqNIaWnySHGI="
},
"kotlinx-coroutines-debug-1.8.0.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-debug/1.8.0/kotlinx-coroutines-debug-1.8.0.pom",
"hash": "sha256-EZPR60nUsUgNqlrGIBctfcmZFidM2Ra+NpQVLA5vb3w="
}
},
"org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.8.1": { "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.8.1": {
"kotlinx-coroutines-jdk8-1.8.1.jar": { "kotlinx-coroutines-jdk8-1.8.1.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-jdk8/1.8.1/kotlinx-coroutines-jdk8-1.8.1.jar", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-jdk8/1.8.1/kotlinx-coroutines-jdk8-1.8.1.jar",
@@ -1958,10 +1798,6 @@
} }
}, },
"org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.8.0": { "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.8.0": {
"kotlinx-coroutines-jdk8-1.8.0.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-jdk8/1.8.0/kotlinx-coroutines-jdk8-1.8.0.jar",
"hash": "sha256-2EGf2zy6quxAfmKrFL5WQ20edrW/MyRMV2VWH8E/0Gs="
},
"kotlinx-coroutines-jdk8-1.8.0.module": { "kotlinx-coroutines-jdk8-1.8.0.module": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-jdk8/1.8.0/kotlinx-coroutines-jdk8-1.8.0.module", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-jdk8/1.8.0/kotlinx-coroutines-jdk8-1.8.0.module",
"hash": "sha256-HKyxz+5adTBFR1rzCF+4DcnMzjA3VKnVIApB3/W+AOk=" "hash": "sha256-HKyxz+5adTBFR1rzCF+4DcnMzjA3VKnVIApB3/W+AOk="
@@ -2015,32 +1851,12 @@
"hash": "sha256-4qht+xaCAWeYuVoPAGy0tdAQRsVaAS6hs2vSAjLcVXQ=" "hash": "sha256-4qht+xaCAWeYuVoPAGy0tdAQRsVaAS6hs2vSAjLcVXQ="
} }
}, },
"org.jetbrains.kotlinx:kotlinx-coroutines-test-jvm:1.8.0": {
"kotlinx-coroutines-test-jvm-1.8.0.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-test-jvm/1.8.0/kotlinx-coroutines-test-jvm-1.8.0.jar",
"hash": "sha256-FTXMH0MjXYVm+NW8bRwR8HBBF+TlY/Ls5+aqPmhpXyA="
},
"kotlinx-coroutines-test-jvm-1.8.0.module": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-test-jvm/1.8.0/kotlinx-coroutines-test-jvm-1.8.0.module",
"hash": "sha256-HS0Zc6L0GowMEmPmCyXneS9ji4xV18ocbQZztkvlfac="
},
"kotlinx-coroutines-test-jvm-1.8.0.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-test-jvm/1.8.0/kotlinx-coroutines-test-jvm-1.8.0.pom",
"hash": "sha256-BtHlPqNm5to7FxkwV1+RYnzxnkUqTnqfDeMNLwQdZFE="
}
},
"org.jetbrains.kotlinx:kotlinx-serialization-bom:1.6.3": { "org.jetbrains.kotlinx:kotlinx-serialization-bom:1.6.3": {
"kotlinx-serialization-bom-1.6.3.pom": { "kotlinx-serialization-bom-1.6.3.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-serialization-bom/1.6.3/kotlinx-serialization-bom-1.6.3.pom", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-serialization-bom/1.6.3/kotlinx-serialization-bom-1.6.3.pom",
"hash": "sha256-KdaYQrt9RJviqkreakp85qpVgn0KsT0Wh0X+bZVzkzI=" "hash": "sha256-KdaYQrt9RJviqkreakp85qpVgn0KsT0Wh0X+bZVzkzI="
} }
}, },
"org.jetbrains.kotlinx:kotlinx-serialization-bom:1.6.2": {
"kotlinx-serialization-bom-1.6.2.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-serialization-bom/1.6.2/kotlinx-serialization-bom-1.6.2.pom",
"hash": "sha256-ew4dde6GIUmc+VQwyhL9qjL0p/kg1cMBv+lfoYfyczc="
}
},
"org.jetbrains.kotlinx:kotlinx-serialization-core:1.6.3": { "org.jetbrains.kotlinx:kotlinx-serialization-core:1.6.3": {
"kotlinx-serialization-core-1.6.3.jar": { "kotlinx-serialization-core-1.6.3.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-serialization-core/1.6.3/kotlinx-serialization-core-1.6.3.jar", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-serialization-core/1.6.3/kotlinx-serialization-core-1.6.3.jar",
@@ -2055,16 +1871,6 @@
"hash": "sha256-0tv2/BU2TIlp1qq24+zMdROZU/LMBXtzDjUmdGWztX4=" "hash": "sha256-0tv2/BU2TIlp1qq24+zMdROZU/LMBXtzDjUmdGWztX4="
} }
}, },
"org.jetbrains.kotlinx:kotlinx-serialization-core:1.6.2": {
"kotlinx-serialization-core-1.6.2.module": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-serialization-core/1.6.2/kotlinx-serialization-core-1.6.2.module",
"hash": "sha256-arz0gTrJTfA3AS4xZzaKNEUHD9+OqyHQjYhtTtnC+2c="
},
"kotlinx-serialization-core-1.6.2.pom": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-serialization-core/1.6.2/kotlinx-serialization-core-1.6.2.pom",
"hash": "sha256-BibddZLIUwKToOPoHgiBltNRh3o422hHaTY3S6ZJ+S8="
}
},
"org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.6.3": { "org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.6.3": {
"kotlinx-serialization-core-jvm-1.6.3.jar": { "kotlinx-serialization-core-jvm-1.6.3.jar": {
"url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-serialization-core-jvm/1.6.3/kotlinx-serialization-core-jvm-1.6.3.jar", "url": "https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-serialization-core-jvm/1.6.3/kotlinx-serialization-core-jvm-1.6.3.jar",

View File

@@ -19,123 +19,143 @@
# ''; # '';
# } # }
{ lib {
, stdenv lib,
, buildEnv stdenv,
, fetchs3 buildEnv,
, fetchurl fetchs3,
, gradle fetchurl,
, maven gradle,
, runCommandLocal maven,
, symlinkJoin runCommandLocal,
, writeText symlinkJoin,
, writeTextDir writeText,
writeTextDir,
}: }:
let defaultGradle = gradle; in let
defaultGradle = gradle;
in
{ {
# Path to the lockfile generated by gradle2nix (e.g. gradle.lock). # Path to the lockfile generated by gradle2nix (e.g. gradle.lock).
lockFile ? null lockFile ? null,
, pname ? "project" pname ? "project",
, version ? null version ? null,
, enableParallelBuilding ? true enableParallelBuilding ? true,
# The Gradle package to use. Default is 'pkgs.gradle'. # The Gradle package to use. Default is 'pkgs.gradle'.
, gradle ? defaultGradle gradle ? defaultGradle,
# Arguments to Gradle used to build the project in buildPhase. # Arguments to Gradle used to build the project in buildPhase.
, gradleFlags ? [ "build" ] gradleFlags ? [ "build" ],
# Enable debugging for the Gradle build; this will cause Gradle to run # Enable debugging for the Gradle build; this will cause Gradle to run
# a debug server and wait for a JVM debugging client to attach. # a debug server and wait for a JVM debugging client to attach.
, enableDebug ? false enableDebug ? false,
# Additional code to run in the Gradle init script (init.gradle). # Additional code to run in the Gradle init script (init.gradle).
, extraInit ? "" extraInit ? "",
# Override the default JDK used to run Gradle itself. # Override the default JDK used to run Gradle itself.
, buildJdk ? null buildJdk ? null,
# Override functions which fetch dependency artifacts. # Override functions which fetch dependency artifacts.
# Keys in this set are URL schemes such as "https" or "s3". # Keys in this set are URL schemes such as "https" or "s3".
# Values are functions which take a dependency in the form # Values are functions which take a dependency in the form
# `{ urls, hash }` and fetch into the Nix store. For example: # `{ urls, hash }` and fetch into the Nix store. For example:
# #
# { # {
# s3 = { name, urls, hash }: fetchs3 { # s3 = { name, urls, hash }: fetchs3 {
# s3url = builtins.head urls; # s3url = builtins.head urls;
# # TODO This doesn't work without patching fetchs3 to accept SRI hashes # # TODO This doesn't work without patching fetchs3 to accept SRI hashes
# inherit name hash; # inherit name hash;
# region = "us-west-2"; # region = "us-west-2";
# credentials = { # credentials = {
# access_key_id = "foo"; # access_key_id = "foo";
# secret_access_key = "bar"; # secret_access_key = "bar";
# }; # };
# }; # };
# } # }
, fetchers ? { } fetchers ? { },
# Overlays for dependencies in the offline Maven repository. # Overlays for dependencies in the offline Maven repository.
# #
# Acceps an attrset of dependencies (usually parsed from 'lockFile'), and produces an attrset # Acceps an attrset of dependencies (usually parsed from 'lockFile'), and produces an attrset
# containing dependencies to merge into the final set. # containing dependencies to merge into the final set.
# #
# The attrset is of the form: # The attrset is of the form:
# #
# { # {
# "${group}:${module}:${version}" = <derivation>; # "${group}:${module}:${version}" = <derivation>;
# # ... # # ...
# } # }
# #
# A dependency derivation unpacks multiple source files into a single Maven-style directory named # A dependency derivation unpacks multiple source files into a single Maven-style directory named
# "${out}/${groupPath}/${module}/${version}/", where 'groupPath' is the dependency group ID with dot # "${out}/${groupPath}/${module}/${version}/", where 'groupPath' is the dependency group ID with dot
# characters ('.') replaced by the path separator ('/'). # characters ('.') replaced by the path separator ('/').
# #
# Examples: # Examples:
# #
# 1. Add or replace a dependency with a single JAR file: # 1. Add or replace a dependency with a single JAR file:
# #
# (_: { # (_: {
# "com.squareup.okio:okio:3.9.0" = fetchurl { # "com.squareup.okio:okio:3.9.0" = fetchurl {
# url = "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/3.9.0/okio-3.9.0.jar"; # url = "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/3.9.0/okio-3.9.0.jar";
# hash = "..."; # hash = "...";
# downloadToTemmp = true; # downloadToTemmp = true;
# postFetch = "install -Dt $out/com/squareup/okio/okio/3.9.0/ $downloadedFile" # postFetch = "install -Dt $out/com/squareup/okio/okio/3.9.0/ $downloadedFile"
# }; # };
# }) # })
# #
# 2. Remove a dependency entirely: # 2. Remove a dependency entirely:
# #
# # This works because the result is filtered for values that are derivations. # # This works because the result is filtered for values that are derivations.
# (_: { # (_: {
# "org.apache.log4j:core:2.23.1" = null; # "org.apache.log4j:core:2.23.1" = null;
# }) # })
, overlays ? [] overlays ? [ ],
, ... } @ args: ...
}@args:
let let
inherit (builtins) inherit (builtins)
attrValues concatStringsSep elemAt filter fromJSON getAttr head length mapAttrs removeAttrs attrValues
replaceStrings; concatStringsSep
elemAt
filter
fromJSON
getAttr
head
length
mapAttrs
removeAttrs
replaceStrings
;
inherit (lib) inherit (lib)
mapAttrsToList optionalString readFile versionAtLeast versionOlder; mapAttrsToList
optionalString
readFile
versionAtLeast
versionOlder
;
inherit (lib.strings) sanitizeDerivationName; inherit (lib.strings) sanitizeDerivationName;
toCoordinates = id: toCoordinates =
id:
let let
coords = builtins.split ":" id; coords = builtins.split ":" id;
parseVersion = version: parseVersion =
version:
let let
parts = builtins.split ":" version; parts = builtins.split ":" version;
base = elemAt parts 0; base = elemAt parts 0;
in in
if length parts >= 2 if length parts >= 2 then
then
let let
snapshot = elemAt parts 2; snapshot = elemAt parts 2;
in in
replaceStrings [ "-SNAPSHOT" ] [ "-${snapshot}" ] base replaceStrings [ "-SNAPSHOT" ] [ "-${snapshot}" ] base
else else
base; base;
in
in rec { rec {
group = elemAt coords 0; group = elemAt coords 0;
module = elemAt coords 2; module = elemAt coords 2;
version = elemAt coords 4; version = elemAt coords 4;
@@ -150,17 +170,20 @@ let
# Fetch urls using the scheme for the first entry only; there isn't a # Fetch urls using the scheme for the first entry only; there isn't a
# straightforward way to tell Nix to try multiple fetchers in turn # straightforward way to tell Nix to try multiple fetchers in turn
# and short-circuit on the first successful fetch. # and short-circuit on the first successful fetch.
fetch = name: { url, hash }: fetch =
name:
{ url, hash }:
let let
scheme = head (builtins.match "([a-z0-9+.-]+)://.*" url); scheme = head (builtins.match "([a-z0-9+.-]+)://.*" url);
fetch' = getAttr scheme fetchers'; fetch' = getAttr scheme fetchers';
in in
fetch' { inherit url hash; }; fetch' { inherit url hash; };
mkModule = id: artifacts: mkModule =
id: artifacts:
let let
coords = toCoordinates id; coords = toCoordinates id;
modulePath = "${replaceStrings ["."] ["/"] coords.group}/${coords.module}/${coords.version}"; modulePath = "${replaceStrings [ "." ] [ "/" ] coords.group}/${coords.module}/${coords.version}";
in in
stdenv.mkDerivation { stdenv.mkDerivation {
pname = sanitizeDerivationName "${coords.group}-${coords.module}"; pname = sanitizeDerivationName "${coords.group}-${coords.module}";
@@ -195,11 +218,15 @@ let
# derivation created with 'mkModule'. This allows users extra flexibility # derivation created with 'mkModule'. This allows users extra flexibility
# to do things like patching native libraries with patchelf or replacing # to do things like patching native libraries with patchelf or replacing
# artifacts entirely. # artifacts entirely.
lockedDependencies = final: if lockFile == null then {} else lockedDependencies =
final:
if lockFile == null then
{ }
else
let let
lockedDependencySpecs = fromJSON (readFile lockFile); lockedDependencySpecs = fromJSON (readFile lockFile);
in mapAttrs mkModule lockedDependencySpecs; in
mapAttrs mkModule lockedDependencySpecs;
finalDependencies = finalDependencies =
let let
@@ -261,14 +288,25 @@ let
${extraInit} ${extraInit}
''; '';
buildGradlePackage = stdenv.mkDerivation (finalAttrs: { buildGradlePackage = stdenv.mkDerivation (
finalAttrs:
{
inherit buildJdk enableParallelBuilding enableDebug gradle gradleFlags pname version; inherit
buildJdk
enableParallelBuilding
enableDebug
gradle
gradleFlags
pname
version
;
dontStrip = true; dontStrip = true;
nativeBuildInputs = [ finalAttrs.gradle ] nativeBuildInputs = [
++ lib.optional (finalAttrs.buildJdk != null) finalAttrs.buildJdk; finalAttrs.gradle
] ++ lib.optional (finalAttrs.buildJdk != null) finalAttrs.buildJdk;
buildPhase = '' buildPhase = ''
runHook preBuild runHook preBuild
@@ -292,7 +330,9 @@ let
-Dmaven.repo.local=${offlineRepo} \ -Dmaven.repo.local=${offlineRepo} \
${optionalString finalAttrs.enableParallelBuilding "--parallel"} \ ${optionalString finalAttrs.enableParallelBuilding "--parallel"} \
${optionalString finalAttrs.enableDebug "-Dorg.gradle.debug=true"} \ ${optionalString finalAttrs.enableDebug "-Dorg.gradle.debug=true"} \
${optionalString (finalAttrs.buildJdk != null) "-Dorg.gradle.java.home=${finalAttrs.buildJdk.home}"} \ ${
optionalString (finalAttrs.buildJdk != null) "-Dorg.gradle.java.home=${finalAttrs.buildJdk.home}"
} \
--init-script ${initScript} \ --init-script ${initScript} \
${concatStringsSep " " finalAttrs.gradleFlags} ${concatStringsSep " " finalAttrs.gradleFlags}
) )
@@ -303,12 +343,13 @@ let
passthru = { passthru = {
inherit offlineRepo; inherit offlineRepo;
}; };
} // removeAttrs args [ }
// removeAttrs args [
"lockFile" "lockFile"
"extraInit" "extraInit"
"fetchers" "fetchers"
"overlays" "overlays"
]); ]
);
in in
buildGradlePackage buildGradlePackage

View File

@@ -2,4 +2,4 @@ org.gradle.jvmargs='-Dfile.encoding=UTF-8'
org.gradle.caching=true org.gradle.caching=true
org.gradle.configuration-cache=true org.gradle.configuration-cache=true
VERSION=1.0.0-rc2 VERSION=2.0.0

View File

@@ -1,7 +1,7 @@
[versions] [versions]
gradle = "8.7" gradle = "8.7"
junit = "5.8.2" junit = "5.8.2"
kotlin = "1.9.22" kotlin = "1.9.24"
ktor = "2.3.11" ktor = "2.3.11"
kotest = "5.9.0" kotest = "5.9.0"
@@ -16,7 +16,7 @@ ktor-server-netty = { module = "io.ktor:ktor-server-netty", version.ref = "ktor"
okio = "com.squareup.okio:okio:3.9.0" okio = "com.squareup.okio:okio:3.9.0"
serialization-json = "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3" serialization-json = "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3"
slf4j-simple = "org.slf4j:slf4j-simple:1.7.36" slf4j-simple = "org.slf4j:slf4j-simple:1.7.36"
xmlutil = "io.github.pdvrieze.xmlutil:serialization-jvm:+" xmlutil = "io.github.pdvrieze.xmlutil:serialization-jvm:0.90.0-RC1"
[plugins] [plugins]
pluginPublish = { id = "com.gradle.plugin-publish", version = "1.2.1" } pluginPublish = { id = "com.gradle.plugin-publish", version = "1.2.1" }

View File

@@ -20,7 +20,8 @@ interface DependencyCoordinates : Serializable {
*/ */
val timestamp: String? val timestamp: String?
val id: String get() = if (timestamp != null) { val id: String get() =
if (timestamp != null) {
"$group:$artifact:$version:$timestamp" "$group:$artifact:$version:$timestamp"
} else { } else {
"$group:$artifact:$version" "$group:$artifact:$version"

View File

@@ -1,4 +1,4 @@
package org.nixos.gradle2nix.model package org.nixos.gradle2nix.model
const val RESOLVE_PROJECT_TASK = "resolveProjectDependencies" const val RESOLVE_PROJECT_TASK = "resolveProjectArtifacts"
const val RESOLVE_ALL_TASK = "resolveAllDependencies" const val RESOLVE_ALL_TASK = "resolveAllArtifacts"

View File

@@ -6,9 +6,8 @@ data class DefaultDependencyCoordinates(
override val group: String, override val group: String,
override val artifact: String, override val artifact: String,
override val version: String, override val version: String,
override val timestamp: String? = null override val timestamp: String? = null,
) : DependencyCoordinates { ) : DependencyCoordinates {
override val timestampedCoordinates: DependencyCoordinates override val timestampedCoordinates: DependencyCoordinates
get() = DefaultDependencyCoordinates(group, artifact, timestampedVersion) get() = DefaultDependencyCoordinates(group, artifact, timestampedVersion)
@@ -21,7 +20,7 @@ data class DefaultDependencyCoordinates(
3 -> DefaultDependencyCoordinates(parts[0], parts[1], parts[2]) 3 -> DefaultDependencyCoordinates(parts[0], parts[1], parts[2])
4 -> DefaultDependencyCoordinates(parts[0], parts[1], parts[2], parts[3]) 4 -> DefaultDependencyCoordinates(parts[0], parts[1], parts[2], parts[3])
else -> throw IllegalStateException( else -> throw IllegalStateException(
"couldn't parse dependency coordinates: '$id'" "couldn't parse dependency coordinates: '$id'",
) )
} }
} }

View File

@@ -4,5 +4,5 @@ import org.nixos.gradle2nix.model.DependencySet
import org.nixos.gradle2nix.model.ResolvedDependency import org.nixos.gradle2nix.model.ResolvedDependency
data class DefaultDependencySet( data class DefaultDependencySet(
override val dependencies: List<ResolvedDependency> override val dependencies: List<ResolvedDependency>,
) : DependencySet ) : DependencySet

View File

@@ -1,4 +1,5 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
plugins { plugins {
id("org.jetbrains.kotlin.jvm") id("org.jetbrains.kotlin.jvm")
@@ -11,8 +12,6 @@ dependencies {
shadow(kotlin("reflect")) shadow(kotlin("reflect"))
implementation(project(":model")) implementation(project(":model"))
implementation(libs.serialization.json) implementation(libs.serialization.json)
testImplementation(libs.kotest.assertions)
testImplementation(libs.kotest.runner)
} }
java { java {
@@ -22,7 +21,10 @@ java {
kotlin { kotlin {
compilerOptions { compilerOptions {
apiVersion.set(KotlinVersion.KOTLIN_1_6)
languageVersion.set(KotlinVersion.KOTLIN_1_6)
jvmTarget.set(JvmTarget.JVM_1_8) jvmTarget.set(JvmTarget.JVM_1_8)
optIn.add("kotlin.RequiresOptIn")
} }
} }
@@ -56,11 +58,4 @@ tasks {
validatePlugins { validatePlugins {
enableStricterValidation.set(true) enableStricterValidation.set(true)
} }
withType<Test> {
useJUnitPlatform()
testLogging {
events("passed", "skipped", "failed")
}
}
} }

View File

@@ -1,7 +1,5 @@
package org.nixos.gradle2nix.dependencygraph package org.nixos.gradle2nix
import java.io.File
import java.util.concurrent.ConcurrentHashMap
import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
@@ -11,6 +9,8 @@ import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.jsonPrimitive
import org.gradle.api.internal.artifacts.ivyservice.ArtifactCachesProvider import org.gradle.api.internal.artifacts.ivyservice.ArtifactCachesProvider
import org.gradle.api.internal.artifacts.ivyservice.modulecache.FileStoreAndIndexProvider import org.gradle.api.internal.artifacts.ivyservice.modulecache.FileStoreAndIndexProvider
import org.gradle.api.services.BuildService
import org.gradle.api.services.BuildServiceParameters
import org.gradle.internal.hash.ChecksumService import org.gradle.internal.hash.ChecksumService
import org.gradle.internal.operations.BuildOperationDescriptor import org.gradle.internal.operations.BuildOperationDescriptor
import org.gradle.internal.operations.BuildOperationListener import org.gradle.internal.operations.BuildOperationListener
@@ -26,20 +26,52 @@ import org.nixos.gradle2nix.model.impl.DefaultDependencyCoordinates
import org.nixos.gradle2nix.model.impl.DefaultDependencySet import org.nixos.gradle2nix.model.impl.DefaultDependencySet
import org.nixos.gradle2nix.model.impl.DefaultResolvedArtifact import org.nixos.gradle2nix.model.impl.DefaultResolvedArtifact
import org.nixos.gradle2nix.model.impl.DefaultResolvedDependency import org.nixos.gradle2nix.model.impl.DefaultResolvedDependency
import java.io.File
import java.util.concurrent.ConcurrentHashMap
class DependencyExtractor( internal abstract class DependencyExtractorService :
private val artifactCachesProvider: ArtifactCachesProvider, BuildService<BuildServiceParameters.None>, BuildOperationListener, AutoCloseable {
private val checksumService: ChecksumService, var extractor: DependencyExtractor? = null
private val fileStoreAndIndexProvider: FileStoreAndIndexProvider,
) : BuildOperationListener {
override fun started(
buildOperation: BuildOperationDescriptor,
startEvent: OperationStartEvent,
) {}
override fun progress(
operationIdentifier: OperationIdentifier,
progressEvent: OperationProgressEvent,
) {}
override fun finished(
buildOperation: BuildOperationDescriptor,
finishEvent: OperationFinishEvent,
) {
extractor?.finished(buildOperation, finishEvent)
}
override fun close() {
extractor = null
}
}
class DependencyExtractor : BuildOperationListener {
private val urls = ConcurrentHashMap<String, Unit>() private val urls = ConcurrentHashMap<String, Unit>()
override fun started(buildOperation: BuildOperationDescriptor, startEvent: OperationStartEvent) {} override fun started(
buildOperation: BuildOperationDescriptor,
startEvent: OperationStartEvent,
) {}
override fun progress(operationIdentifier: OperationIdentifier, progressEvent: OperationProgressEvent) {} override fun progress(
operationIdentifier: OperationIdentifier,
progressEvent: OperationProgressEvent,
) {}
override fun finished(buildOperation: BuildOperationDescriptor, finishEvent: OperationFinishEvent) { override fun finished(
buildOperation: BuildOperationDescriptor,
finishEvent: OperationFinishEvent,
) {
when (val details = buildOperation.details) { when (val details = buildOperation.details) {
is ExternalResourceReadBuildOperationType.Details -> urls.computeIfAbsent(details.location) { Unit } is ExternalResourceReadBuildOperationType.Details -> urls.computeIfAbsent(details.location) { Unit }
is ExternalResourceReadMetadataBuildOperationType.Details -> urls.computeIfAbsent(details.location) { Unit } is ExternalResourceReadMetadataBuildOperationType.Details -> urls.computeIfAbsent(details.location) { Unit }
@@ -47,7 +79,11 @@ class DependencyExtractor(
} ?: return } ?: return
} }
fun buildDependencySet(): DependencySet { fun buildDependencySet(
artifactCachesProvider: ArtifactCachesProvider,
checksumService: ChecksumService,
fileStoreAndIndexProvider: FileStoreAndIndexProvider,
): DependencySet {
val files = mutableMapOf<DependencyCoordinates, MutableMap<File, String>>() val files = mutableMapOf<DependencyCoordinates, MutableMap<File, String>>()
val mappings = mutableMapOf<DependencyCoordinates, Map<String, String>>() val mappings = mutableMapOf<DependencyCoordinates, Map<String, String>>()
@@ -69,23 +105,28 @@ class DependencyExtractor(
} }
return DefaultDependencySet( return DefaultDependencySet(
dependencies = buildList { dependencies =
buildList {
for ((componentId, componentFiles) in files) { for ((componentId, componentFiles) in files) {
add(DefaultResolvedDependency( add(
DefaultResolvedDependency(
componentId, componentId,
buildList { buildList {
val remoteMappings = mappings[componentId] val remoteMappings = mappings[componentId]
for ((file, url) in componentFiles) { for ((file, url) in componentFiles) {
add(DefaultResolvedArtifact( add(
DefaultResolvedArtifact(
remoteMappings?.get(file.name) ?: file.name, remoteMappings?.get(file.name) ?: file.name,
checksumService.sha256(file).toString(), checksumService.sha256(file).toString(),
url url,
)) ),
} )
}
))
} }
},
),
)
} }
},
) )
} }
} }
@@ -98,7 +139,8 @@ private fun cachedComponentId(file: File): DependencyCoordinates? {
} }
@OptIn(ExperimentalSerializationApi::class) @OptIn(ExperimentalSerializationApi::class)
private fun parseFileMappings(file: File): Map<String, String>? = try { private fun parseFileMappings(file: File): Map<String, String>? =
try {
Json.decodeFromStream<JsonObject>(file.inputStream()) Json.decodeFromStream<JsonObject>(file.inputStream())
.jsonObject["variants"]?.jsonArray .jsonObject["variants"]?.jsonArray
?.flatMap { it.jsonObject["files"]?.jsonArray ?: emptyList() } ?.flatMap { it.jsonObject["files"]?.jsonArray ?: emptyList() }
@@ -110,6 +152,6 @@ private fun parseFileMappings(file: File): Map<String, String>? = try {
} }
?.toMap() ?.toMap()
?.takeUnless { it.isEmpty() } ?.takeUnless { it.isEmpty() }
} catch (e: Throwable) { } catch (e: Throwable) {
null null
} }

View File

@@ -2,53 +2,91 @@
package org.nixos.gradle2nix package org.nixos.gradle2nix
import javax.inject.Inject
import org.gradle.api.Plugin import org.gradle.api.Plugin
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.internal.artifacts.ivyservice.ArtifactCachesProvider
import org.gradle.api.internal.artifacts.ivyservice.modulecache.FileStoreAndIndexProvider
import org.gradle.api.invocation.Gradle import org.gradle.api.invocation.Gradle
import org.gradle.internal.hash.ChecksumService
import org.gradle.tooling.provider.model.ToolingModelBuilder import org.gradle.tooling.provider.model.ToolingModelBuilder
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
import org.nixos.gradle2nix.dependencygraph.DependencyExtractor import org.gradle.util.GradleVersion
import org.nixos.gradle2nix.forceresolve.ForceDependencyResolutionPlugin
import org.nixos.gradle2nix.model.DependencySet import org.nixos.gradle2nix.model.DependencySet
import org.nixos.gradle2nix.util.artifactCachesProvider import org.nixos.gradle2nix.model.RESOLVE_ALL_TASK
import org.nixos.gradle2nix.util.buildOperationListenerManager import javax.inject.Inject
import org.nixos.gradle2nix.util.checksumService
import org.nixos.gradle2nix.util.fileStoreAndIndexProvider
abstract class Gradle2NixPlugin @Inject constructor(
private val toolingModelBuilderRegistry: ToolingModelBuilderRegistry
): Plugin<Gradle> {
abstract class Gradle2NixPlugin
@Inject
constructor(
private val toolingModelBuilderRegistry: ToolingModelBuilderRegistry,
) : Plugin<Gradle> {
override fun apply(gradle: Gradle) { override fun apply(gradle: Gradle) {
val dependencyExtractor = DependencyExtractor( val dependencyExtractor = DependencyExtractor()
toolingModelBuilderRegistry.register(
DependencySetModelBuilder(
dependencyExtractor,
gradle.artifactCachesProvider, gradle.artifactCachesProvider,
gradle.checksumService, gradle.checksumService,
gradle.fileStoreAndIndexProvider, gradle.fileStoreAndIndexProvider,
),
) )
toolingModelBuilderRegistry.register(DependencySetModelBuilder(dependencyExtractor)) if (GradleVersion.current() < GradleVersion.version("8.0")) {
val extractor = DependencyExtractor()
gradle.buildOperationListenerManager.addListener(extractor)
gradle.buildOperationListenerManager.addListener(dependencyExtractor)
// Configuration caching is not enabled with dependency verification so this is fine for now.
// Gradle 9.x might remove this though.
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
gradle.buildFinished { gradle.buildFinished {
gradle.buildOperationListenerManager.removeListener(dependencyExtractor) gradle.buildOperationListenerManager.removeListener(extractor)
}
} else {
val serviceProvider =
gradle.sharedServices.registerIfAbsent(
"nixDependencyExtractor",
DependencyExtractorService::class.java,
).map { service ->
service.apply { extractor = dependencyExtractor }
} }
gradle.pluginManager.apply(ForceDependencyResolutionPlugin::class.java) gradle.buildEventListenerRegistryInternal.onOperationCompletion(serviceProvider)
}
gradle.projectsEvaluated {
val resolveAll = gradle.rootProject.tasks.register(RESOLVE_ALL_TASK)
// Depend on "dependencies" task in all projects
gradle.allprojects { project ->
val resolveProject = project.createResolveTask()
resolveAll.configure { it.dependsOn(resolveProject) }
}
// Depend on all 'resolveBuildDependencies' task in each included build
gradle.includedBuilds.forEach { includedBuild ->
resolveAll.configure {
it.dependsOn(includedBuild.task(":$RESOLVE_ALL_TASK"))
}
}
}
}
} }
}
internal class DependencySetModelBuilder( internal class DependencySetModelBuilder(
private val dependencyExtractor: DependencyExtractor, private val dependencyExtractor: DependencyExtractor,
private val artifactCachesProvider: ArtifactCachesProvider,
private val checksumService: ChecksumService,
private val fileStoreAndIndexProvider: FileStoreAndIndexProvider,
) : ToolingModelBuilder { ) : ToolingModelBuilder {
override fun canBuild(modelName: String): Boolean = modelName == DependencySet::class.qualifiedName override fun canBuild(modelName: String): Boolean = modelName == DependencySet::class.qualifiedName
override fun buildAll(modelName: String, project: Project): DependencySet { override fun buildAll(
return dependencyExtractor.buildDependencySet() modelName: String,
project: Project,
): DependencySet {
return dependencyExtractor.buildDependencySet(
artifactCachesProvider,
checksumService,
fileStoreAndIndexProvider,
)
} }
} }

View File

@@ -0,0 +1,42 @@
package org.nixos.gradle2nix
import org.gradle.api.artifacts.Configuration
import org.gradle.api.internal.GradleInternal
import org.gradle.api.internal.artifacts.ivyservice.ArtifactCachesProvider
import org.gradle.api.internal.artifacts.ivyservice.modulecache.FileStoreAndIndexProvider
import org.gradle.api.invocation.Gradle
import org.gradle.internal.build.event.BuildEventListenerRegistryInternal
import org.gradle.internal.hash.ChecksumService
import org.gradle.internal.operations.BuildOperationListenerManager
import org.gradle.util.GradleVersion
import java.lang.reflect.Method
internal inline val Gradle.artifactCachesProvider: ArtifactCachesProvider
get() = service()
internal inline val Gradle.buildEventListenerRegistryInternal: BuildEventListenerRegistryInternal
get() = service()
internal inline val Gradle.buildOperationListenerManager: BuildOperationListenerManager
get() = service()
internal inline val Gradle.checksumService: ChecksumService
get() = service()
internal inline val Gradle.fileStoreAndIndexProvider: FileStoreAndIndexProvider
get() = service()
internal inline fun <reified T> Gradle.service(): T = (this as GradleInternal).services.get(T::class.java)
private val canSafelyBeResolvedMethod: Method? =
try {
val dc = Class.forName("org.gradle.internal.deprecation.DeprecatableConfiguration")
dc.getMethod("canSafelyBeResolved")
} catch (e: ReflectiveOperationException) {
null
}
internal fun Configuration.canSafelyBeResolved(): Boolean = canSafelyBeResolvedMethod?.invoke(this) as? Boolean ?: isCanBeResolved
internal val gradleVersionIsAtLeast8: Boolean =
GradleVersion.current() >= GradleVersion.version("8.0")

View File

@@ -0,0 +1,66 @@
package org.nixos.gradle2nix
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.component.ModuleComponentIdentifier
import org.gradle.api.file.FileCollection
import org.gradle.api.model.ObjectFactory
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.TaskProvider
import org.gradle.internal.serialization.Cached
import org.gradle.work.DisableCachingByDefault
import org.nixos.gradle2nix.model.RESOLVE_PROJECT_TASK
import javax.inject.Inject
internal fun Project.createResolveTask(): TaskProvider<out Task> {
return if (gradleVersionIsAtLeast8) {
tasks.register(RESOLVE_PROJECT_TASK, ResolveProjectDependenciesTask::class.java)
} else {
tasks.register(RESOLVE_PROJECT_TASK, LegacyResolveProjectDependenciesTask::class.java)
}
}
@DisableCachingByDefault(because = "Not worth caching")
sealed class AbstractResolveProjectDependenciesTask : DefaultTask() {
@Internal
protected fun getReportableConfigurations(): List<Configuration> {
return project.configurations.filter { it.canSafelyBeResolved() }
}
}
@DisableCachingByDefault(because = "Not worth caching")
abstract class LegacyResolveProjectDependenciesTask : AbstractResolveProjectDependenciesTask() {
@TaskAction
fun action() {
for (configuration in getReportableConfigurations()) {
configuration.incoming.resolutionResult.root
}
}
}
@DisableCachingByDefault(because = "Not worth caching")
abstract class ResolveProjectDependenciesTask
@Inject
constructor(
private val objects: ObjectFactory,
) : AbstractResolveProjectDependenciesTask() {
private val artifactFiles = Cached.of { artifactFiles() }
private fun artifactFiles(): FileCollection {
return objects.fileCollection().from(
getReportableConfigurations().map { configuration ->
configuration.incoming.artifactView { viewConfiguration ->
viewConfiguration.componentFilter { it is ModuleComponentIdentifier }
}.files
},
)
}
@TaskAction
fun action() {
artifactFiles.get().count()
}
}

View File

@@ -1,15 +0,0 @@
package org.nixos.gradle2nix.forceresolve
import org.gradle.api.DefaultTask
import org.gradle.api.artifacts.Configuration
import org.gradle.api.tasks.Internal
import org.gradle.work.DisableCachingByDefault
import org.nixos.gradle2nix.util.canSafelyBeResolved
@DisableCachingByDefault(because = "Not worth caching")
abstract class AbstractResolveProjectDependenciesTask : DefaultTask() {
@Internal
protected fun getReportableConfigurations(): List<Configuration> {
return project.configurations.filter { it.canSafelyBeResolved() }
}
}

View File

@@ -1,63 +0,0 @@
package org.nixos.gradle2nix.forceresolve
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.model.RESOLVE_ALL_TASK
import org.nixos.gradle2nix.model.RESOLVE_PROJECT_TASK
// TODO: Rename these
/**
* Adds a task to resolve all dependencies in a Gradle build tree.
*/
class ForceDependencyResolutionPlugin : Plugin<Gradle> {
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<out Task>
data object Current : ResolveProjectDependenciesTaskFactory {
override fun create(project: Project): TaskProvider<out Task> {
return project.tasks.register(RESOLVE_PROJECT_TASK, ResolveProjectDependenciesTask::class.java)
}
}
data object Legacy : ResolveProjectDependenciesTaskFactory {
override fun create(project: Project): TaskProvider<out Task> {
return project.tasks.register(RESOLVE_PROJECT_TASK, LegacyResolveProjectDependenciesTask::class.java)
}
}
}
}

View File

@@ -1,16 +0,0 @@
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 : AbstractResolveProjectDependenciesTask() {
@TaskAction
fun action() {
for (configuration in getReportableConfigurations()) {
configuration.incoming.resolutionResult.root
}
}
}

View File

@@ -1,31 +0,0 @@
package org.nixos.gradle2nix.forceresolve
import javax.inject.Inject
import org.gradle.api.artifacts.component.ModuleComponentIdentifier
import org.gradle.api.file.FileCollection
import org.gradle.api.model.ObjectFactory
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 @Inject constructor(
private val objects: ObjectFactory
): AbstractResolveProjectDependenciesTask() {
private val artifactFiles = Cached.of { artifactFiles() }
private fun artifactFiles(): FileCollection {
return objects.fileCollection().from(
getReportableConfigurations().map { configuration ->
configuration.incoming.artifactView { viewConfiguration ->
viewConfiguration.componentFilter { it is ModuleComponentIdentifier }
}.files
}
)
}
@TaskAction
fun action() {
artifactFiles.get().count()
}
}

View File

@@ -1,36 +0,0 @@
package org.nixos.gradle2nix.util
import java.lang.reflect.Method
import org.gradle.api.artifacts.Configuration
import org.gradle.api.internal.GradleInternal
import org.gradle.api.internal.artifacts.ivyservice.ArtifactCachesProvider
import org.gradle.api.internal.artifacts.ivyservice.modulecache.FileStoreAndIndexProvider
import org.gradle.api.invocation.Gradle
import org.gradle.internal.hash.ChecksumService
import org.gradle.internal.operations.BuildOperationAncestryTracker
import org.gradle.internal.operations.BuildOperationListenerManager
internal inline val Gradle.artifactCachesProvider: ArtifactCachesProvider
get() = service()
internal inline val Gradle.buildOperationListenerManager: BuildOperationListenerManager
get() = service()
internal inline val Gradle.checksumService: ChecksumService
get() = service()
internal inline val Gradle.fileStoreAndIndexProvider: FileStoreAndIndexProvider
get() = service()
internal inline fun <reified T> Gradle.service(): T =
(this as GradleInternal).services.get(T::class.java)
private val canSafelyBeResolvedMethod: Method? = try {
val dc = Class.forName("org.gradle.internal.deprecation.DeprecatableConfiguration")
dc.getMethod("canSafelyBeResolved")
} catch (e: ReflectiveOperationException) {
null
}
internal fun Configuration.canSafelyBeResolved(): Boolean =
canSafelyBeResolvedMethod?.invoke(this) as? Boolean ?: isCanBeResolved