From 121e512a06eb46965f08e18bc05a4645c515b642 Mon Sep 17 00:00:00 2001 From: Tad Fisher Date: Wed, 11 Oct 2023 13:29:21 -0700 Subject: [PATCH] Update metadata parsing --- app/build.gradle.kts | 1 + .../kotlin/org/nixos/gradle2nix/Logger.kt | 34 +- .../main/kotlin/org/nixos/gradle2nix/Main.kt | 12 +- .../kotlin/org/nixos/gradle2nix/Process.kt | 137 +- .../dependency/ComponentArtifactIdentifier.kt | 31 - .../dependency/ComponentIdentifier.kt | 28 - .../ModuleComponentArtifactIdentifier.kt | 40 - .../dependency/ModuleComponentIdentifier.kt | 76 - .../gradle2nix/dependency/ModuleIdentifier.kt | 40 - .../metadata/ArtifactVerificationMetadata.kt | 6 - .../org/nixos/gradle2nix/metadata/Checksum.kt | 43 - .../nixos/gradle2nix/metadata/ChecksumKind.kt | 30 - .../metadata/ComponentVerificationMetadata.kt | 8 - .../DependencyVerificationConfiguration.kt | 98 - .../metadata/DependencyVerificationXmlTags.kt | 48 - .../DependencyVerificationsXmlReader.kt | 421 -- .../gradle2nix/metadata/DependencyVerifier.kt | 23 - .../metadata/DependencyVerifierBuilder.kt | 162 - .../metadata/VerificationMetadata.kt | 142 + .../nixos/gradle2nix/module/GradleModule.kt | 102 + .../kotlin/org/nixos/gradle2nix/TestUtil.kt | 6 + .../gradle2nix/VerificationMetadataTest.kt | 17 + fixtures/metadata/verification-metadata.xml | 5292 +++++++++++++++++ flake.lock | 30 +- gradle/libs.versions.toml | 3 +- .../nixos/gradle2nix/DependencyCoordinates.kt | 4 +- plugin/build.gradle.kts | 2 - .../org/nixos/gradle2nix/Gradle2NixPlugin.kt | 1 + .../ForceDependencyResolutionPlugin.kt | 6 +- 29 files changed, 5708 insertions(+), 1135 deletions(-) delete mode 100644 app/src/main/kotlin/org/nixos/gradle2nix/dependency/ComponentArtifactIdentifier.kt delete mode 100644 app/src/main/kotlin/org/nixos/gradle2nix/dependency/ComponentIdentifier.kt delete mode 100644 app/src/main/kotlin/org/nixos/gradle2nix/dependency/ModuleComponentArtifactIdentifier.kt delete mode 100644 app/src/main/kotlin/org/nixos/gradle2nix/dependency/ModuleComponentIdentifier.kt delete mode 100644 app/src/main/kotlin/org/nixos/gradle2nix/dependency/ModuleIdentifier.kt delete mode 100644 app/src/main/kotlin/org/nixos/gradle2nix/metadata/ArtifactVerificationMetadata.kt delete mode 100644 app/src/main/kotlin/org/nixos/gradle2nix/metadata/Checksum.kt delete mode 100644 app/src/main/kotlin/org/nixos/gradle2nix/metadata/ChecksumKind.kt delete mode 100644 app/src/main/kotlin/org/nixos/gradle2nix/metadata/ComponentVerificationMetadata.kt delete mode 100644 app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerificationConfiguration.kt delete mode 100644 app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerificationXmlTags.kt delete mode 100644 app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerificationsXmlReader.kt delete mode 100644 app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerifier.kt delete mode 100644 app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerifierBuilder.kt create mode 100644 app/src/main/kotlin/org/nixos/gradle2nix/metadata/VerificationMetadata.kt create mode 100644 app/src/main/kotlin/org/nixos/gradle2nix/module/GradleModule.kt create mode 100644 app/src/test/kotlin/org/nixos/gradle2nix/VerificationMetadataTest.kt create mode 100644 fixtures/metadata/verification-metadata.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3f194ea..2bb5458 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -17,6 +17,7 @@ dependencies { implementation(libs.slf4j.api) runtimeOnly(libs.slf4j.simple) implementation(libs.okio) + implementation(libs.xmlutil) "share"(project(":plugin", configuration = "shadow")) diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/Logger.kt b/app/src/main/kotlin/org/nixos/gradle2nix/Logger.kt index 9191481..4b13022 100644 --- a/app/src/main/kotlin/org/nixos/gradle2nix/Logger.kt +++ b/app/src/main/kotlin/org/nixos/gradle2nix/Logger.kt @@ -5,17 +5,35 @@ import kotlin.system.exitProcess class Logger( val out: PrintStream = System.err, - val verbose: Boolean + val verbose: Boolean, + val stacktrace: Boolean = false ) { - val log: (String) -> Unit = { if (verbose) out.println(it) } - val warn: (String) -> Unit = { out.println("Warning: $it")} - val error: (String) -> Nothing = { - out.println("Error: $it") + fun log(message: String, error: Throwable? = null) { + if (!verbose) return + out.println(message) + if (error == null) return + error.message?.let { println(" Cause: $it") } + if (stacktrace) error.printStackTrace(out) + } + + fun warn(message: String, error: Throwable? = null) { + out.println("Warning: $message") + if (error == null) return + error.message?.let { println(" Cause: $it") } + if (stacktrace) error.printStackTrace(out) + } + + fun error(message: String, error: Throwable? = null): Nothing { + out.println("Error: $message") + if (error != null) { + error.message?.let { println(" Cause: $it") } + if (stacktrace) error.printStackTrace(out) + } exitProcess(1) } - operator fun component1() = log - operator fun component2() = warn - operator fun component3() = error + operator fun component1() = ::log + operator fun component2() = ::warn + operator fun component3() = ::error } diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/Main.kt b/app/src/main/kotlin/org/nixos/gradle2nix/Main.kt index 9580351..50fd69b 100644 --- a/app/src/main/kotlin/org/nixos/gradle2nix/Main.kt +++ b/app/src/main/kotlin/org/nixos/gradle2nix/Main.kt @@ -30,7 +30,8 @@ data class Config( ) @OptIn(ExperimentalSerializationApi::class) -private val JsonFormat = Json { +val JsonFormat = Json { + ignoreUnknownKeys = true prettyPrint = true prettyPrintIndent = " " } @@ -106,9 +107,6 @@ class Gradle2Nix : CliktCommand( } } - // Visible for testing - lateinit var config: Config - @OptIn(ExperimentalSerializationApi::class) override fun run() { val appHome = System.getProperty("org.nixos.gradle2nix.share") @@ -118,7 +116,7 @@ class Gradle2Nix : CliktCommand( val gradleHome = System.getenv("GRADLE_USER_HOME")?.let(::File) ?: File("${System.getProperty("user.home")}/.gradle") val logger = Logger(verbose = !quiet) - config = Config( + val config = Config( File(appHome), gradleHome, gradleVersion, @@ -131,8 +129,6 @@ class Gradle2Nix : CliktCommand( logger ) - val (log, _, error) = logger - val metadata = File("$projectDir/gradle/verification-metadata.xml") if (metadata.exists()) { val backup = metadata.resolveSibling("verification-metadata.xml.bak") @@ -158,7 +154,7 @@ class Gradle2Nix : CliktCommand( val outDir = outDir ?: projectDir val json = outDir.resolve("$envFile.json") - log("Writing environment to $json") + logger.log("Writing environment to $json") json.outputStream().buffered().use { output -> JsonFormat.encodeToStream(dependencies, output) } diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/Process.kt b/app/src/main/kotlin/org/nixos/gradle2nix/Process.kt index a45fd19..a7de618 100644 --- a/app/src/main/kotlin/org/nixos/gradle2nix/Process.kt +++ b/app/src/main/kotlin/org/nixos/gradle2nix/Process.kt @@ -1,9 +1,12 @@ package org.nixos.gradle2nix +import org.nixos.gradle2nix.metadata.Artifact as ArtifactMetadata import java.io.File -import java.io.FileFilter +import java.io.IOException import java.net.URI +import java.net.URL import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.SerializationException import kotlinx.serialization.json.Json import kotlinx.serialization.json.decodeFromStream import okio.ByteString.Companion.decodeHex @@ -11,16 +14,19 @@ import okio.HashingSource import okio.blackholeSink import okio.buffer import okio.source -import org.nixos.gradle2nix.dependency.ModuleComponentIdentifier import org.nixos.gradle2nix.dependencygraph.model.DependencyCoordinates import org.nixos.gradle2nix.dependencygraph.model.Repository import org.nixos.gradle2nix.dependencygraph.model.ResolvedConfiguration -import org.nixos.gradle2nix.metadata.ArtifactVerificationMetadata import org.nixos.gradle2nix.metadata.Checksum -import org.nixos.gradle2nix.metadata.ChecksumKind -import org.nixos.gradle2nix.metadata.ComponentVerificationMetadata -import org.nixos.gradle2nix.metadata.DependencyVerificationsXmlReader -import org.nixos.gradle2nix.metadata.DependencyVerifier +import org.nixos.gradle2nix.metadata.Component +import org.nixos.gradle2nix.metadata.Md5 +import org.nixos.gradle2nix.metadata.Sha1 +import org.nixos.gradle2nix.metadata.Sha256 +import org.nixos.gradle2nix.metadata.Sha512 +import org.nixos.gradle2nix.metadata.VerificationMetadata +import org.nixos.gradle2nix.metadata.parseVerificationMetadata +import org.nixos.gradle2nix.module.GradleModule +import org.nixos.gradle2nix.module.Variant // Local Maven repository for testing private val m2 = System.getProperty("org.nixos.gradle2nix.m2") @@ -31,7 +37,11 @@ private fun shouldSkipRepository(repository: Repository): Boolean { } fun processDependencies(config: Config): Map> { - val verifier = readVerificationMetadata(config) + val verificationMetadata = readVerificationMetadata(config) + val verificationComponents = verificationMetadata?.components?.associateBy { + DependencyCoordinates(it.group, it.name, it.version) + } ?: emptyMap() + val moduleCache = mutableMapOf() val configurations = readDependencyGraph(config) val repositories = configurations @@ -61,15 +71,10 @@ fun processDependencies(config: Config): Map> { return@mapNotNull null } val coordinates = deps.first().coordinates - val componentId = ModuleComponentIdentifier( - coordinates.group, - coordinates.module, - coordinates.version - ) - val metadata = verifier.verificationMetadata[componentId] - ?: verifyComponentFilesInCache(config, componentId) - ?: verifyComponentFilesInTestRepository(config, componentId) - if (metadata == null) { + val component = verificationComponents[coordinates] + ?: verifyComponentFilesInCache(config, coordinates) + ?: verifyComponentFilesInTestRepository(config, coordinates) + if (component == null) { config.logger.warn("$id: not present in metadata or cache; skipping") return@mapNotNull null } @@ -85,23 +90,25 @@ fun processDependencies(config: Config): Map> { return@mapNotNull null } - id to metadata.artifactVerifications.associate { meta -> - meta.artifactName to Artifact( + val gradleModule = moduleCache.getOrPut(coordinates) { + maybeGetGradleModule(config.logger, coordinates, repos) + } + + id to component.artifacts.associate { meta -> + meta.name to Artifact( urls = repos - .flatMap { repository -> artifactUrls(coordinates, meta, repository) } + .flatMap { repository -> artifactUrls(coordinates, meta.name, repository, gradleModule) } .distinct(), - hash = meta.checksums.maxBy { c -> c.kind.ordinal }.toSri() + hash = meta.checksums.first().toSri() ) } } + .sortedBy { it.first } .toMap() } -private fun readVerificationMetadata(config: Config): DependencyVerifier { - return config.projectDir.resolve("gradle/verification-metadata.xml") - .inputStream() - .buffered() - .use { input -> DependencyVerificationsXmlReader.readFromXml(input) } +private fun readVerificationMetadata(config: Config): VerificationMetadata? { + return parseVerificationMetadata(config.logger, config.projectDir.resolve("gradle/verification-metadata.xml")) } @OptIn(ExperimentalSerializationApi::class) @@ -114,40 +121,58 @@ private fun readDependencyGraph(config: Config): List { private fun verifyComponentFilesInCache( config: Config, - component: ModuleComponentIdentifier -): ComponentVerificationMetadata? { - val cacheDir = config.gradleHome.resolve("caches/modules-2/files-2.1/${component.group}/${component.module}/${component.version}") + coordinates: DependencyCoordinates, +): Component? { + val cacheDir = with(coordinates) { config.gradleHome.resolve("caches/modules-2/files-2.1/$group/$module/$version") } if (!cacheDir.exists()) { return null } val verifications = cacheDir.walk().filter { it.isFile }.map { f -> - ArtifactVerificationMetadata( - f.name, - listOf(Checksum(ChecksumKind.sha256, f.sha256())) - ) + ArtifactMetadata(f.name, sha256 = Sha256(f.sha256())) } - config.logger.log("$component: obtained artifact hashes from Gradle cache.") - return ComponentVerificationMetadata(component, verifications.toList()) + config.logger.log("$coordinates: obtained artifact hashes from Gradle cache.") + return Component(coordinates, verifications.toList()) } private fun verifyComponentFilesInTestRepository( config: Config, - component: ModuleComponentIdentifier -): ComponentVerificationMetadata? { + coordinates: DependencyCoordinates +): Component? { if (m2 == null) return null - val dir = File(URI.create(m2)).resolve("${component.group.replace(".", "/")}/${component.module}/${component.version}") + val dir = with(coordinates) { + File(URI.create(m2)).resolve("${group.replace(".", "/")}/$module/$version") + } if (!dir.exists()) { - config.logger.log("$component: not found in m2 repository; tried $dir") + config.logger.log("$coordinates: not found in m2 repository; tried $dir") return null } - val verifications = dir.walk().filter { it.isFile && it.name.startsWith(component.module) }.map { f -> - ArtifactVerificationMetadata( + val verifications = dir.walk().filter { it.isFile && it.name.startsWith(coordinates.module) }.map { f -> + ArtifactMetadata( f.name, - listOf(Checksum(ChecksumKind.sha256, f.sha256())) + sha256 = Sha256(f.sha256()) ) } - config.logger.log("$component: obtained artifact hashes from test Maven repository.") - return ComponentVerificationMetadata(component, verifications.toList()) + config.logger.log("$coordinates: obtained artifact hashes from test Maven repository.") + return Component(coordinates, verifications.toList()) +} + +@OptIn(ExperimentalSerializationApi::class) +private fun maybeGetGradleModule(logger: Logger, coordinates: DependencyCoordinates, repos: List): GradleModule? { + val filename = with(coordinates) { "$module-$version.module" } + + for (url in repos.flatMap { artifactUrls(coordinates, filename, it, null)}) { + try { + return URL(url).openStream().buffered().use { input -> + JsonFormat.decodeFromStream(input) + } + } catch (e: SerializationException) { + logger.error("$coordinates: failed to parse Gradle module metadata ($url)", e) + } catch (e: IOException) { + // Pass + } + } + + return null } private fun File.sha256(): String { @@ -158,26 +183,34 @@ private fun File.sha256(): String { private fun Checksum.toSri(): String { val hash = value.decodeHex().base64() - return when (kind) { - ChecksumKind.md5 -> "md5-$hash" - ChecksumKind.sha1 -> "sha1-$hash" - ChecksumKind.sha256 -> "sha256-$hash" - ChecksumKind.sha512 -> "sha512-$hash" + return when (this) { + is Md5 -> "md5-$hash" + is Sha1 -> "sha1-$hash" + is Sha256 -> "sha256-$hash" + is Sha512 -> "sha512-$hash" } } private fun artifactUrls( coordinates: DependencyCoordinates, - metadata: ArtifactVerificationMetadata, - repository: Repository + filename: String, + repository: Repository, + module: GradleModule? ): List { val groupAsPath = coordinates.group.replace(".", "/") + val repoFilename = module?.let { m -> + m.variants + .asSequence() + .flatMap(Variant::files) + .find { it.name == filename } + }?.url ?: filename + val attributes = mutableMapOf( "organisation" to if (repository.m2Compatible) groupAsPath else coordinates.group, "module" to coordinates.module, "revision" to coordinates.version, - ) + fileAttributes(metadata.artifactName, coordinates.version) + ) + fileAttributes(repoFilename, coordinates.version) val resources = when (attributes["ext"]) { "pom" -> if ("mavenPom" in repository.metadataSources) repository.metadataResources else repository.artifactResources diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ComponentArtifactIdentifier.kt b/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ComponentArtifactIdentifier.kt deleted file mode 100644 index e4788ee..0000000 --- a/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ComponentArtifactIdentifier.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.nixos.gradle2nix.dependency - -/** - * An opaque immutable identifier for an artifact that belongs to some component instance. - */ -interface ComponentArtifactIdentifier { - /** - * Returns the id of the component that this artifact belongs to. - */ - val componentIdentifier: ComponentIdentifier - - /** - * Returns some human-consumable display name for this artifact. - */ - val displayName: String -} diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ComponentIdentifier.kt b/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ComponentIdentifier.kt deleted file mode 100644 index 83b0bfc..0000000 --- a/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ComponentIdentifier.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.nixos.gradle2nix.dependency - -/** - * An opaque immutable identifier for a component instance. There are various sub-interfaces that expose specific details about the identifier. - */ -interface ComponentIdentifier { - /** - * Returns a human-consumable display name for this identifier. - * - * @return Component identifier display name - */ - val displayName: String -} diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ModuleComponentArtifactIdentifier.kt b/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ModuleComponentArtifactIdentifier.kt deleted file mode 100644 index 298284a..0000000 --- a/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ModuleComponentArtifactIdentifier.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.nixos.gradle2nix.dependency - -/** - * An immutable identifier for an artifact that belongs to some module version. - */ -interface ModuleComponentArtifactIdentifier : ComponentArtifactIdentifier { - /** - * Returns the id of the component that this artifact belongs to. - */ - override val componentIdentifier: ModuleComponentIdentifier - - /** - * Returns a file base name that can be used for this artifact. - */ - val fileName: String -} - -data class DefaultModuleComponentArtifactIdentifier( - override val componentIdentifier: ModuleComponentIdentifier, - override val fileName: String, -) : ModuleComponentArtifactIdentifier { - override val displayName: String get() = "$fileName ($componentIdentifier)" - - override fun toString(): String = displayName -} diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ModuleComponentIdentifier.kt b/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ModuleComponentIdentifier.kt deleted file mode 100644 index 8be353b..0000000 --- a/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ModuleComponentIdentifier.kt +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.nixos.gradle2nix.dependency - -/** - * An identifier for a component instance which is available as a module version. - */ -interface ModuleComponentIdentifier : ComponentIdentifier { - /** - * The module group of the component. - * - * @return Component group - */ - val group: String - - /** - * The module name of the component. - * - * @return Component module - */ - val module: String - - /** - * The module version of the component. - * - * @return Component version - */ - val version: String - - /** - * The module identifier of the component. Returns the same information - * as [group] and [module]. - * - * @return the module identifier - */ - val moduleIdentifier: ModuleIdentifier -} - -data class DefaultModuleComponentIdentifier( - override val moduleIdentifier: ModuleIdentifier, - override val version: String, -) : ModuleComponentIdentifier { - override val group: String - get() = moduleIdentifier.group - - override val module: String - get() = moduleIdentifier.name - - override val displayName: String - get() = "$group:$module:$version" - - override fun toString(): String = displayName -} - - -fun ModuleComponentIdentifier( - group: String, - module: String, - version: String -): ModuleComponentIdentifier = DefaultModuleComponentIdentifier( - DefaultModuleIdentifier(group, module), - version -) diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ModuleIdentifier.kt b/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ModuleIdentifier.kt deleted file mode 100644 index 5457f3f..0000000 --- a/app/src/main/kotlin/org/nixos/gradle2nix/dependency/ModuleIdentifier.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.nixos.gradle2nix.dependency - -/** - * The identifier of a module. - */ -interface ModuleIdentifier { - /** - * The group of the module. - * - * @return module group - */ - val group: String - - /** - * The name of the module. - * - * @return module name - */ - val name: String -} - -data class DefaultModuleIdentifier( - override val group: String, - override val name: String, -) : ModuleIdentifier diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/ArtifactVerificationMetadata.kt b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/ArtifactVerificationMetadata.kt deleted file mode 100644 index ae67531..0000000 --- a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/ArtifactVerificationMetadata.kt +++ /dev/null @@ -1,6 +0,0 @@ -package org.nixos.gradle2nix.metadata - -data class ArtifactVerificationMetadata( - val artifactName: String, - val checksums: List -) diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/Checksum.kt b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/Checksum.kt deleted file mode 100644 index a5c84ef..0000000 --- a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/Checksum.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.nixos.gradle2nix.metadata - -/** - * Internal representation of a checksum, aimed at *verification*. - * A checksum consists of a kind (md5, sha1, ...), a value, but also - * provides *alternatives*. Alternatives are checksums which are - * deemed trusted, because sometimes in a single build we can see different - * checksums for the same module, because they are sourced from different - * repositories. - * - * In theory, this shouldn't be allowed. However, it's often the case that - * an artifact, in particular _metadata artifacts_ (POM files, ...) differ - * from one repository to the other (either by end of lines, additional line - * at the end of the file, ...). Because they are different doesn't mean that - * they are compromised, so this is a facility for the user to declare "I know - * I should use a single source of truth but the infrastructure is hard or - * impossible to fix so let's trust this source". - * - * In addition to the list of alternatives, a checksum also provides a source, - * which is documentation to explain where a checksum was found. - */ -data class Checksum( - val kind: ChecksumKind, - val value: String, - val alternatives: Set = emptySet(), - val origin: String? = null, - val reason: String? = null -) diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/ChecksumKind.kt b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/ChecksumKind.kt deleted file mode 100644 index 6469cf7..0000000 --- a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/ChecksumKind.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.nixos.gradle2nix.metadata - -enum class ChecksumKind(val algorithm: String) { - md5("MD5"), - sha1("SHA1"), - sha256("SHA-256"), - sha512("SHA-512"); - - companion object { - private val SORTED_BY_SECURITY: List = listOf(sha512, sha256, sha1, md5) - fun mostSecureFirst(): List { - return SORTED_BY_SECURITY - } - } -} diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/ComponentVerificationMetadata.kt b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/ComponentVerificationMetadata.kt deleted file mode 100644 index 54e454c..0000000 --- a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/ComponentVerificationMetadata.kt +++ /dev/null @@ -1,8 +0,0 @@ -package org.nixos.gradle2nix.metadata - -import org.nixos.gradle2nix.dependency.ModuleComponentIdentifier - -data class ComponentVerificationMetadata( - val componentId: ModuleComponentIdentifier, - val artifactVerifications: List, -) diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerificationConfiguration.kt b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerificationConfiguration.kt deleted file mode 100644 index 8bfbf18..0000000 --- a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerificationConfiguration.kt +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.nixos.gradle2nix.metadata - -import org.nixos.gradle2nix.dependency.ModuleComponentArtifactIdentifier -import org.nixos.gradle2nix.dependency.ModuleComponentIdentifier - -class DependencyVerificationConfiguration( - val trustedArtifacts: List = emptyList(), -) { - data class TrustCoordinates internal constructor( - val group: String?, - val name: String?, - val version: String?, - val fileName: String?, - val isRegex: Boolean, - val reason: String? - ) : Comparable { - - fun matches(id: ModuleComponentArtifactIdentifier): Boolean { - val moduleComponentIdentifier: ModuleComponentIdentifier = id.componentIdentifier - return (matches(group, moduleComponentIdentifier.group) - && matches(name, moduleComponentIdentifier.module) - && matches(version, moduleComponentIdentifier.version) - && matches(fileName, id.fileName)) - } - - private fun matches(value: String?, expr: String): Boolean { - if (value == null) { - return true - } - return if (!isRegex) { - expr == value - } else expr.matches(value.toRegex()) - } - - override fun compareTo(other: TrustCoordinates): Int { - val regexComparison = isRegex.compareTo(other.isRegex) - if (regexComparison != 0) { - return regexComparison - } - val groupComparison = compareNullableStrings( - group, other.group - ) - if (groupComparison != 0) { - return groupComparison - } - val nameComparison = compareNullableStrings( - name, other.name - ) - if (nameComparison != 0) { - return nameComparison - } - val versionComparison = compareNullableStrings( - version, other.version - ) - if (versionComparison != 0) { - return versionComparison - } - val fileNameComparison = compareNullableStrings( - fileName, other.fileName - ) - return if (fileNameComparison != 0) { - fileNameComparison - } else compareNullableStrings( - reason, other.reason - ) - } - } - - companion object { - private fun compareNullableStrings(first: String?, second: String?): Int { - if (first == null) { - return if (second == null) { - 0 - } else { - -1 - } - } else if (second == null) { - return 1 - } - return first.compareTo(second) - } - } -} diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerificationXmlTags.kt b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerificationXmlTags.kt deleted file mode 100644 index b6e019a..0000000 --- a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerificationXmlTags.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.nixos.gradle2nix.metadata - -internal object DependencyVerificationXmlTags { - const val ALSO_TRUST = "also-trust" - const val ARTIFACT = "artifact" - const val COMPONENT = "component" - const val COMPONENTS = "components" - const val CONFIG = "configuration" - const val ENABLED = "enabled" - const val FILE = "file" - const val GROUP = "group" - const val ID = "id" - const val IGNORED_KEY = "ignored-key" - const val IGNORED_KEYS = "ignored-keys" - const val KEY_SERVER = "key-server" - const val KEY_SERVERS = "key-servers" - const val NAME = "name" - const val ORIGIN = "origin" - const val PGP = "pgp" - const val REASON = "reason" - const val REGEX = "regex" - const val TRUST = "trust" - const val TRUSTED_ARTIFACTS = "trusted-artifacts" - const val TRUSTED_KEY = "trusted-key" - const val TRUSTED_KEYS = "trusted-keys" - const val TRUSTING = "trusting" - const val URI = "uri" - const val VALUE = "value" - const val VERIFICATION_METADATA = "verification-metadata" - const val VERIFY_METADATA = "verify-metadata" - const val VERIFY_SIGNATURES = "verify-signatures" - const val VERSION = "version" -} diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerificationsXmlReader.kt b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerificationsXmlReader.kt deleted file mode 100644 index 2976931..0000000 --- a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerificationsXmlReader.kt +++ /dev/null @@ -1,421 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.nixos.gradle2nix.metadata - -import java.io.IOException -import java.io.InputStream -import javax.xml.parsers.ParserConfigurationException -import javax.xml.parsers.SAXParser -import javax.xml.parsers.SAXParserFactory -import org.gradle.internal.UncheckedException -import org.nixos.gradle2nix.dependency.DefaultModuleComponentArtifactIdentifier -import org.nixos.gradle2nix.dependency.DefaultModuleComponentIdentifier -import org.nixos.gradle2nix.dependency.DefaultModuleIdentifier -import org.nixos.gradle2nix.dependency.ModuleComponentArtifactIdentifier -import org.nixos.gradle2nix.dependency.ModuleComponentIdentifier -import org.nixos.gradle2nix.dependency.ModuleIdentifier -import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.ALSO_TRUST -import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.ARTIFACT -import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.COMPONENT -import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.COMPONENTS -import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.CONFIG -import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.IGNORED_KEY -import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.IGNORED_KEYS -import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.KEY_SERVER -import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.KEY_SERVERS -import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.PGP -import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.TRUST -import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.TRUSTED_ARTIFACTS -import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.TRUSTED_KEY -import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.TRUSTED_KEYS -import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.TRUSTING -import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.VALUE -import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.VERIFICATION_METADATA -import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.VERIFY_METADATA -import org.nixos.gradle2nix.metadata.DependencyVerificationXmlTags.VERIFY_SIGNATURES -import org.xml.sax.Attributes -import org.xml.sax.InputSource -import org.xml.sax.SAXException -import org.xml.sax.ext.DefaultHandler2 - -object DependencyVerificationsXmlReader { - fun readFromXml( - input: InputStream, - builder: DependencyVerifierBuilder - ) { - try { - val saxParser = createSecureParser() - val xmlReader = saxParser.xmlReader - val handler = VerifiersHandler(builder) - xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler", handler) - xmlReader.contentHandler = handler - xmlReader.parse(InputSource(input)) - } catch (e: Exception) { - throw IllegalStateException( - "Unable to read dependency verification metadata", - e - ) - } finally { - try { - input.close() - } catch (e: IOException) { - throw UncheckedException.throwAsUncheckedException(e) - } - } - } - - fun readFromXml(input: InputStream): DependencyVerifier { - val builder = DependencyVerifierBuilder() - readFromXml(input, builder) - return builder.build() - } - - @Throws(ParserConfigurationException::class, SAXException::class) - private fun createSecureParser(): SAXParser { - val spf = SAXParserFactory.newInstance() - spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false) - spf.setFeature("http://xml.org/sax/features/namespaces", false) - spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true) - return spf.newSAXParser() - } - - private class VerifiersHandler(private val builder: DependencyVerifierBuilder) : DefaultHandler2() { - private var inMetadata = false - private var inComponents = false - private var inConfiguration = false - private var inVerifyMetadata = false - private var inVerifySignatures = false - private var inTrustedArtifacts = false - private var inKeyServers = false - private var inIgnoredKeys = false - private var inTrustedKeys = false - private var inTrustedKey = false - private var currentTrustedKey: String? = null - private var currentComponent: ModuleComponentIdentifier? = null - private var currentArtifact: ModuleComponentArtifactIdentifier? = - null - private var currentChecksum: ChecksumKind? = null - - override fun startElement(uri: String, localName: String, qName: String, attributes: Attributes) { - when (qName) { - CONFIG -> inConfiguration = - true - - VERIFICATION_METADATA -> inMetadata = - true - - COMPONENTS -> { - assertInMetadata() - inComponents = true - } - - COMPONENT -> { - assertInComponents() - currentComponent = createComponentId(attributes) - } - - ARTIFACT -> { - assertValidComponent() - currentArtifact = createArtifactId(attributes) - } - - VERIFY_METADATA -> { - assertInConfiguration(VERIFY_METADATA) - inVerifyMetadata = true - } - - VERIFY_SIGNATURES -> { - assertInConfiguration(VERIFY_SIGNATURES) - inVerifySignatures = true - } - - TRUSTED_ARTIFACTS -> { - assertInConfiguration(TRUSTED_ARTIFACTS) - inTrustedArtifacts = true - } - - TRUSTED_KEY -> { - assertContext( - inTrustedKeys, - TRUSTED_KEY, - TRUSTED_KEYS - ) - inTrustedKey = true - } - - TRUSTED_KEYS -> { - assertInConfiguration(TRUSTED_KEYS) - inTrustedKeys = true - } - - TRUST -> { - assertInTrustedArtifacts() - addTrustedArtifact(attributes) - } - - TRUSTING -> { - assertContext( - inTrustedKey, - TRUSTING, - TRUSTED_KEY - ) - } - - KEY_SERVERS -> { - assertInConfiguration(KEY_SERVERS) - inKeyServers = true - } - - KEY_SERVER -> { - assertContext( - inKeyServers, - KEY_SERVER, - KEY_SERVERS - ) - } - - IGNORED_KEYS -> { - if (currentArtifact == null) { - assertInConfiguration(IGNORED_KEYS) - } - inIgnoredKeys = true - } - - IGNORED_KEY -> { - assertContext( - inIgnoredKeys, - IGNORED_KEY, - IGNORED_KEYS - ) - } - - else -> if (currentChecksum != null && ALSO_TRUST == qName) { - builder.addChecksum( - currentArtifact!!, - currentChecksum!!, - getAttribute(attributes, VALUE), - null, - null - ) - } else if (currentArtifact != null) { - if (PGP != qName) { - currentChecksum = enumValueOf(qName) - builder.addChecksum( - currentArtifact!!, - currentChecksum!!, - getAttribute( - attributes, - VALUE - ), - getNullableAttribute( - attributes, - DependencyVerificationXmlTags.ORIGIN - ), - getNullableAttribute( - attributes, - DependencyVerificationXmlTags.REASON - ) - ) - } - } - } - } - - private fun assertInTrustedArtifacts() { - assertContext( - inTrustedArtifacts, - TRUST, - TRUSTED_ARTIFACTS - ) - } - - private fun addTrustedArtifact(attributes: Attributes) { - var regex = false - val regexAttr = getNullableAttribute( - attributes, - DependencyVerificationXmlTags.REGEX - ) - if (regexAttr != null) { - regex = regexAttr.toBoolean() - } - builder.addTrustedArtifact( - getNullableAttribute( - attributes, - DependencyVerificationXmlTags.GROUP - ), - getNullableAttribute( - attributes, - DependencyVerificationXmlTags.NAME - ), - getNullableAttribute( - attributes, - DependencyVerificationXmlTags.VERSION - ), - getNullableAttribute( - attributes, - DependencyVerificationXmlTags.FILE - ), - regex, - getNullableAttribute( - attributes, - DependencyVerificationXmlTags.REASON - ) - ) - } - - private fun readBoolean(ch: CharArray, start: Int, length: Int): Boolean { - return String(ch, start, length).toBoolean() - } - - private fun assertInConfiguration(tag: String) { - assertContext( - inConfiguration, - tag, - DependencyVerificationXmlTags.CONFIG - ) - } - - private fun assertInComponents() { - assertContext( - inComponents, - DependencyVerificationXmlTags.COMPONENT, - DependencyVerificationXmlTags.COMPONENTS - ) - } - - private fun assertInMetadata() { - assertContext( - inMetadata, - DependencyVerificationXmlTags.COMPONENTS, - DependencyVerificationXmlTags.VERIFICATION_METADATA - ) - } - - private fun assertValidComponent() { - assertContext( - currentComponent != null, - ARTIFACT, - DependencyVerificationXmlTags.COMPONENT - ) - } - - override fun endElement(uri: String, localName: String, qName: String) { - when (qName) { - DependencyVerificationXmlTags.CONFIG -> inConfiguration = - false - - VERIFY_METADATA -> inVerifyMetadata = - false - - VERIFY_SIGNATURES -> inVerifySignatures = - false - - DependencyVerificationXmlTags.VERIFICATION_METADATA -> inMetadata = - false - - DependencyVerificationXmlTags.COMPONENTS -> inComponents = - false - - DependencyVerificationXmlTags.COMPONENT -> currentComponent = - null - - TRUSTED_ARTIFACTS -> inTrustedArtifacts = - false - - TRUSTED_KEYS -> inTrustedKeys = - false - - TRUSTED_KEY -> { - inTrustedKey = false - currentTrustedKey = null - } - - KEY_SERVERS -> inKeyServers = - false - - ARTIFACT -> { - currentArtifact = null - currentChecksum = null - } - - IGNORED_KEYS -> inIgnoredKeys = - false - } - } - - private fun createArtifactId(attributes: Attributes): ModuleComponentArtifactIdentifier { - return DefaultModuleComponentArtifactIdentifier( - currentComponent!!, - getAttribute( - attributes, - DependencyVerificationXmlTags.NAME - ) - ) - } - - private fun createComponentId(attributes: Attributes): ModuleComponentIdentifier { - return DefaultModuleComponentIdentifier( - createModuleId(attributes), - getAttribute( - attributes, - DependencyVerificationXmlTags.VERSION - ) - ) - } - - private fun createModuleId(attributes: Attributes): ModuleIdentifier { - return DefaultModuleIdentifier( - getAttribute( - attributes, - DependencyVerificationXmlTags.GROUP - ), - getAttribute( - attributes, - DependencyVerificationXmlTags.NAME - ) - ) - } - - private fun getAttribute(attributes: Attributes, name: String): String { - val value = attributes.getValue(name) - assertContext( - value != null, - "Missing attribute: $name" - ) - return value.intern() - } - - private fun getNullableAttribute(attributes: Attributes, name: String): String? { - val value = attributes.getValue(name) ?: return null - return value.intern() - } - - companion object { - private fun assertContext(test: Boolean, innerTag: String, outerTag: String) { - assertContext( - test, - "<$innerTag> must be found under the <$outerTag> tag" - ) - } - - private fun assertContext(test: Boolean, message: String) { - if (!test) { - throw IllegalStateException("Invalid dependency verification metadata file: $message") - } - } - } - } -} diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerifier.kt b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerifier.kt deleted file mode 100644 index d2639c0..0000000 --- a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerifier.kt +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.nixos.gradle2nix.metadata - -import org.nixos.gradle2nix.dependency.ModuleComponentIdentifier - -class DependencyVerifier internal constructor( - val verificationMetadata: Map, - val configuration: DependencyVerificationConfiguration, -) diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerifierBuilder.kt b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerifierBuilder.kt deleted file mode 100644 index 2eeaa58..0000000 --- a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/DependencyVerifierBuilder.kt +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.nixos.gradle2nix.metadata - -import org.nixos.gradle2nix.dependency.ModuleComponentArtifactIdentifier -import org.nixos.gradle2nix.dependency.ModuleComponentIdentifier - -class DependencyVerifierBuilder { - private val byComponent: MutableMap = mutableMapOf() - private val trustedArtifacts: MutableList = mutableListOf() - - fun addChecksum( - artifact: ModuleComponentArtifactIdentifier, - kind: ChecksumKind, - value: String, - origin: String?, - reason: String? - ) { - val componentIdentifier: ModuleComponentIdentifier = artifact.componentIdentifier - byComponent.getOrPut(componentIdentifier) { - ComponentVerificationsBuilder(componentIdentifier) - }.addChecksum(artifact, kind, value, origin, reason) - } - - @JvmOverloads - fun addTrustedArtifact( - group: String?, - name: String?, - version: String?, - fileName: String?, - regex: Boolean, - reason: String? = null - ) { - validateUserInput(group, name, version, fileName) - trustedArtifacts.add(DependencyVerificationConfiguration.TrustCoordinates(group, name, version, fileName, regex, reason)) - } - - private fun validateUserInput( - group: String?, - name: String?, - version: String?, - fileName: String? - ) { - // because this can be called from parsing XML, we need to perform additional verification - if (group == null && name == null && version == null && fileName == null) { - throw IllegalStateException("A trusted artifact must have at least one of group, name, version or file name not null") - } - } - - fun build(): DependencyVerifier { - return DependencyVerifier( - byComponent - .toSortedMap( - compareBy { it.group } - .thenBy { it.module } - .thenBy { it.version } - ) - .mapValues { it.value.build() }, - DependencyVerificationConfiguration(trustedArtifacts), - ) - } - - private class ComponentVerificationsBuilder(private val component: ModuleComponentIdentifier) { - private val byArtifact: MutableMap = mutableMapOf() - - fun addChecksum( - artifact: ModuleComponentArtifactIdentifier, - kind: ChecksumKind, - value: String, - origin: String?, - reason: String? - ) { - byArtifact.computeIfAbsent(artifact.fileName) { ArtifactVerificationBuilder() } - .addChecksum(kind, value, origin, reason) - } - - fun build(): ComponentVerificationMetadata { - return ComponentVerificationMetadata( - component, - byArtifact - .map { ArtifactVerificationMetadata(it.key, it.value.buildChecksums()) } - .sortedBy { it.artifactName } - ) - } - } - - protected class ArtifactVerificationBuilder { - private val builder: MutableMap = mutableMapOf() - - fun addChecksum(kind: ChecksumKind, value: String, origin: String?, reason: String?) { - val builder = builder.getOrPut(kind) { - ChecksumBuilder(kind) - } - builder.addChecksum(value) - if (origin != null) { - builder.withOrigin(origin) - } - if (reason != null) { - builder.withReason(reason) - } - } - - fun buildChecksums(): List { - return builder.values - .map(ChecksumBuilder::build) - .sortedBy { it.kind } - } - } - - private class ChecksumBuilder(private val kind: ChecksumKind) { - private var value: String? = null - private var origin: String? = null - private var reason: String? = null - private var alternatives: MutableSet = mutableSetOf() - - /** - * Sets the origin, if not set already. This is - * mostly used for automatic generation of checksums - */ - fun withOrigin(origin: String?) { - this.origin = this.origin ?: origin - } - - /** - * Sets the reason, if not set already. - */ - fun withReason(reason: String?) { - this.reason = this.reason ?: reason - } - - fun addChecksum(checksum: String) { - if (value == null) { - value = checksum - } else if (value != checksum) { - alternatives.add(checksum) - } - } - - fun build(): Checksum { - return Checksum( - kind, - checkNotNull(value) { "Checksum is null" }, - alternatives, - origin, - reason - ) - } - } -} diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/VerificationMetadata.kt b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/VerificationMetadata.kt new file mode 100644 index 0000000..53bd895 --- /dev/null +++ b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/VerificationMetadata.kt @@ -0,0 +1,142 @@ +package org.nixos.gradle2nix.metadata + +import java.io.File +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import nl.adaptivity.xmlutil.XmlStreaming +import nl.adaptivity.xmlutil.serialization.XML +import nl.adaptivity.xmlutil.serialization.XmlChildrenName +import nl.adaptivity.xmlutil.serialization.XmlElement +import nl.adaptivity.xmlutil.serialization.XmlSerialName +import org.nixos.gradle2nix.Logger +import org.nixos.gradle2nix.dependencygraph.model.DependencyCoordinates + +sealed interface Coordinates { + val group: String? + val name: String? + val version: String? + val regex: Boolean + val file: String? +} + +@Serializable +@SerialName("trust") +data class Trust( + override val group: String? = null, + override val name: String? = null, + override val version: String? = null, + override val regex: Boolean = false, + override val file: String? = null, + val reason: String? = null, +) : Coordinates + +@Serializable +@SerialName("configuration") +data class Configuration( + @SerialName("verify-metadata") @XmlElement(true) val verifyMetadata: Boolean = false, + @SerialName("verify-signatures") @XmlElement(true) val verifySignatures: Boolean = false, + @SerialName("trusted-artifacts") @XmlChildrenName("trusted-artifacts") val trustedArtifacts: List = emptyList() +) + +@Serializable +sealed interface Checksum { + abstract val value: String + abstract val origin: String? + abstract val reason: String? + abstract val alternatives: List +} + +@Serializable +@SerialName("md5") +data class Md5( + override val value: String, + override val origin: String? = null, + override val reason: String? = null, + @XmlChildrenName("also-trust") + override val alternatives: List = emptyList() +) : Checksum + +@Serializable +@SerialName("sha1") +data class Sha1( + override val value: String, + override val origin: String? = null, + override val reason: String? = null, + @XmlChildrenName("also-trust") + override val alternatives: List = emptyList() +) : Checksum + +@Serializable +@SerialName("sha256") +data class Sha256( + override val value: String, + override val origin: String? = null, + override val reason: String? = null, + @XmlChildrenName("also-trust") + override val alternatives: List = emptyList() +) : Checksum + +@Serializable +@SerialName("sha512") +data class Sha512( + override val value: String, + override val origin: String? = null, + override val reason: String? = null, + @XmlChildrenName("also-trust") + override val alternatives: List = emptyList() +) : Checksum + +@Serializable +@SerialName("artifact") +data class Artifact( + val name: String, + val md5: Md5? = null, + val sha1: Sha1? = null, + val sha256: Sha256? = null, + val sha512: Sha512? = null, +) { + val checksums: List by lazy { listOfNotNull(sha512, sha256, sha1, md5) } +} + +@Serializable +@SerialName("component") +data class Component( + val group: String, + val name: String, + val version: String, + val artifacts: List = emptyList(), +) { + constructor(coordinates: DependencyCoordinates, artifacts: List) : this( + coordinates.group, + coordinates.module, + coordinates.version, + artifacts + ) +} + +@Serializable +@XmlSerialName( + "verification-metadata", + namespace = "https://schema.gradle.org/dependency-verification", + prefix = "" +) +data class VerificationMetadata( + val configuration: Configuration = Configuration(), + @XmlChildrenName("components", "https://schema.gradle.org/dependency-verification") val components: List = emptyList() +) + +val XmlFormat = XML { + autoPolymorphic = true + recommended() +} + +fun parseVerificationMetadata(logger: Logger, metadata: File): VerificationMetadata? { + return try { + metadata.reader().buffered().let(XmlStreaming::newReader).use { input -> + XmlFormat.decodeFromReader(input) + } + } catch (e: Exception) { + logger.warn("$metadata: failed to parse Gradle dependency verification metadata", e) + return null + } +} diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/module/GradleModule.kt b/app/src/main/kotlin/org/nixos/gradle2nix/module/GradleModule.kt new file mode 100644 index 0000000..bc08c63 --- /dev/null +++ b/app/src/main/kotlin/org/nixos/gradle2nix/module/GradleModule.kt @@ -0,0 +1,102 @@ +package org.nixos.gradle2nix.module + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonObject + +@Serializable +data class GradleModule( + val formatVersion: String, + val component: Component? = null, + val createdBy: CreatedBy? = null, + val variants: List = emptyList(), +) + +@Serializable +data class Component( + val group: String, + val module: String, + val version: String, + val url: String? = null, +) + +@Serializable +data class Gradle( + val version: String, + val buildId: String? = null +) + +@Serializable +data class CreatedBy( + val gradle: Gradle? = null +) + +@Serializable +data class Variant( + val name: String, + val attributes: JsonObject? = null, + @SerialName("available-at") val availableAt: AvailableAt? = null, + val dependencies: List = emptyList(), + val dependencyConstraints: List = emptyList(), + val files: List = emptyList(), + val capabilities: List = emptyList() +) + +@Serializable +data class AvailableAt( + val url: String, + val group: String, + val module: String, + val version: String, +) + +@Serializable +data class Dependency( + val group: String, + val module: String, + val version: JsonObject? = null, + val excludes: List = emptyList(), + val reason: String? = null, + val attributes: JsonObject? = null, + val requestedCapabilities: List = emptyList(), + val endorseStrictVersions: Boolean = false, + val thirdPartyCompatibility: ThirdPartyCompatibility? = null, +) + +@Serializable +data class DependencyConstraint( + val group: String, + val module: String, + val version: JsonObject? = null, + val reason: String? = null, + val attributes: JsonObject? = null, +) + +@Serializable +data class VariantFile( + val name: String, + val url: String, + val size: Long, + val sha1: String? = null, + val sha256: String? = null, + val sha512: String? = null, + val md5: String? = null, +) + +@Serializable +data class Capability( + val group: String, + val name: String, + val version: String? = null, +) + +@Serializable +data class Exclude( + val group: String, + val module: String, +) + +@Serializable +data class ThirdPartyCompatibility( + val artifactSelector: String +) diff --git a/app/src/test/kotlin/org/nixos/gradle2nix/TestUtil.kt b/app/src/test/kotlin/org/nixos/gradle2nix/TestUtil.kt index 49b6b07..17fd2e0 100644 --- a/app/src/test/kotlin/org/nixos/gradle2nix/TestUtil.kt +++ b/app/src/test/kotlin/org/nixos/gradle2nix/TestUtil.kt @@ -38,6 +38,12 @@ private val json = Json { prettyPrintIndent = " " } +val testLogger = Logger(verbose = true, stacktrace = true) + +fun fixture(path: String): File { + return Paths.get("../fixtures", path).toFile() +} + @OptIn(ExperimentalKotest::class, ExperimentalSerializationApi::class, KotestInternal::class) suspend fun TestScope.fixture( project: String, diff --git a/app/src/test/kotlin/org/nixos/gradle2nix/VerificationMetadataTest.kt b/app/src/test/kotlin/org/nixos/gradle2nix/VerificationMetadataTest.kt new file mode 100644 index 0000000..de075a3 --- /dev/null +++ b/app/src/test/kotlin/org/nixos/gradle2nix/VerificationMetadataTest.kt @@ -0,0 +1,17 @@ +package org.nixos.gradle2nix + +import io.kotest.core.spec.style.FunSpec +import io.kotest.matchers.nulls.beNull +import io.kotest.matchers.nulls.shouldNotBeNull +import io.kotest.matchers.shouldNot +import kotlinx.serialization.decodeFromString +import org.nixos.gradle2nix.metadata.Artifact +import org.nixos.gradle2nix.metadata.XmlFormat +import org.nixos.gradle2nix.metadata.parseVerificationMetadata + +class VerificationMetadataTest : FunSpec({ + test("parses verification metadata") { + val metadata = parseVerificationMetadata(testLogger, fixture("metadata/verification-metadata.xml")) + metadata shouldNot beNull() + } +}) diff --git a/fixtures/metadata/verification-metadata.xml b/fixtures/metadata/verification-metadata.xml new file mode 100644 index 0000000..8409abf --- /dev/null +++ b/fixtures/metadata/verification-metadata.xml @@ -0,0 +1,5292 @@ + + + + true + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flake.lock b/flake.lock index 6b80d16..e07a8ee 100644 --- a/flake.lock +++ b/flake.lock @@ -1,12 +1,15 @@ { "nodes": { "flake-utils": { + "inputs": { + "systems": "systems" + }, "locked": { - "lastModified": 1605370193, - "narHash": "sha256-YyMTf3URDL/otKdKgtoMChu4vfVL3vCMkRqpGifhUn0=", + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", "owner": "numtide", "repo": "flake-utils", - "rev": "5021eac20303a61fafe17224c087f5519baed54d", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", "type": "github" }, "original": { @@ -17,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1607536117, - "narHash": "sha256-q3xr1fz93VNMnZjpqLN3VyphED2UxO6pd8jR8B4S+lo=", + "lastModified": 1696589439, + "narHash": "sha256-Ye+flokLfswVz9PZEyJ5yGJ1VqmJe3bDgwWt9Z4MuqQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "b8936e55235bb4a970514d4bb9fbd77a2c16b806", + "rev": "e462c9172c685f0839baaa54bb5b49276a23dab7", "type": "github" }, "original": { @@ -36,6 +39,21 @@ "flake-utils": "flake-utils", "nixpkgs": "nixpkgs" } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e9be1d9..a11eef3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] gradle = "8.3" -kotlin = "1.9.0" # Current embedded Gradle kotlin version +kotlin = "1.9.20-Beta2" [libraries] clikt = "com.github.ajalt:clikt:+" @@ -15,6 +15,7 @@ okio = "com.squareup.okio:okio:+" serialization-json = "org.jetbrains.kotlinx:kotlinx-serialization-json:+" slf4j-api = "org.slf4j:slf4j-api:+" slf4j-simple = "org.slf4j:slf4j-simple:+" +xmlutil = "io.github.pdvrieze.xmlutil:serialization-jvm:+" [plugins] pluginPublish = { id = "com.gradle.plugin-publish", version = "1.2.1" } diff --git a/model/src/main/kotlin/org/nixos/gradle2nix/DependencyCoordinates.kt b/model/src/main/kotlin/org/nixos/gradle2nix/DependencyCoordinates.kt index 2f32f94..bba02ca 100644 --- a/model/src/main/kotlin/org/nixos/gradle2nix/DependencyCoordinates.kt +++ b/model/src/main/kotlin/org/nixos/gradle2nix/DependencyCoordinates.kt @@ -3,4 +3,6 @@ package org.nixos.gradle2nix.dependencygraph.model import kotlinx.serialization.Serializable @Serializable -data class DependencyCoordinates(val group: String, val module: String, val version: String) +data class DependencyCoordinates(val group: String, val module: String, val version: String) { + override fun toString(): String = "$group:$module:$version" +} diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index 915e72c..726e2de 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -1,6 +1,4 @@ -import com.github.jengelman.gradle.plugins.shadow.relocation.SimpleRelocator import org.jetbrains.kotlin.gradle.dsl.JvmTarget -import org.jetbrains.kotlin.gradle.utils.extendsFrom plugins { id("org.jetbrains.kotlin.jvm") diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/Gradle2NixPlugin.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/Gradle2NixPlugin.kt index b5a0eac..1fe170c 100644 --- a/plugin/src/main/kotlin/org/nixos/gradle2nix/Gradle2NixPlugin.kt +++ b/plugin/src/main/kotlin/org/nixos/gradle2nix/Gradle2NixPlugin.kt @@ -5,6 +5,7 @@ package org.nixos.gradle2nix import org.gradle.api.Plugin import org.gradle.api.invocation.Gradle import org.nixos.gradle2nix.dependencygraph.AbstractDependencyExtractorPlugin +import org.nixos.gradle2nix.forceresolve.ForceDependencyResolutionPlugin @Suppress("unused") class Gradle2NixPlugin : Plugin { diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/forceresolve/ForceDependencyResolutionPlugin.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/forceresolve/ForceDependencyResolutionPlugin.kt index e5ade2e..eb46431 100644 --- a/plugin/src/main/kotlin/org/nixos/gradle2nix/forceresolve/ForceDependencyResolutionPlugin.kt +++ b/plugin/src/main/kotlin/org/nixos/gradle2nix/forceresolve/ForceDependencyResolutionPlugin.kt @@ -1,4 +1,4 @@ -package org.nixos.gradle2nix +package org.nixos.gradle2nix.forceresolve import org.gradle.api.Plugin import org.gradle.api.Project @@ -6,8 +6,8 @@ import org.gradle.api.Task import org.gradle.api.invocation.Gradle import org.gradle.api.tasks.TaskProvider import org.gradle.util.GradleVersion -import org.nixos.gradle2nix.forceresolve.LegacyResolveProjectDependenciesTask -import org.nixos.gradle2nix.forceresolve.ResolveProjectDependenciesTask +import org.nixos.gradle2nix.RESOLVE_ALL_TASK +import org.nixos.gradle2nix.RESOLVE_PROJECT_TASK // TODO: Rename these