diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/Process.kt b/app/src/main/kotlin/org/nixos/gradle2nix/Process.kt index 104ab41..6050acf 100644 --- a/app/src/main/kotlin/org/nixos/gradle2nix/Process.kt +++ b/app/src/main/kotlin/org/nixos/gradle2nix/Process.kt @@ -21,8 +21,6 @@ import org.nixos.gradle2nix.env.ArtifactSet import org.nixos.gradle2nix.env.Env import org.nixos.gradle2nix.env.Module import org.nixos.gradle2nix.env.ModuleId -import org.nixos.gradle2nix.env.ModuleVersionId -import org.nixos.gradle2nix.env.Version import org.nixos.gradle2nix.metadata.Checksum import org.nixos.gradle2nix.metadata.Component import org.nixos.gradle2nix.metadata.Md5 @@ -31,6 +29,8 @@ 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.model.DependencyCoordinates +import org.nixos.gradle2nix.model.Version import org.nixos.gradle2nix.module.GradleModule import org.nixos.gradle2nix.module.Variant @@ -44,12 +44,10 @@ private fun shouldSkipRepository(repository: Repository): Boolean { fun processDependencies(config: Config): Env { val verificationMetadata = readVerificationMetadata(config) - val verificationComponents = verificationMetadata?.components?.associateBy { - ModuleVersionId(ModuleId(it.group, it.name), it.version) - } ?: emptyMap() - val moduleCache = mutableMapOf() - val pomCache = mutableMapOf?>() - val ivyCache = mutableMapOf?>() + val verificationComponents = verificationMetadata?.components?.associateBy { it.id } ?: emptyMap() + val moduleCache = mutableMapOf() + val pomCache = mutableMapOf?>() + val ivyCache = mutableMapOf?>() val configurations = readDependencyGraph(config) val repositories = configurations @@ -71,15 +69,14 @@ fun processDependencies(config: Config): Env { return configurations.asSequence() .flatMap { it.allDependencies.asSequence() } - .filterNot { it.id.startsWith("project ") || it.repository == null || it.repository !in repositories } - .groupBy { ModuleId(it.coordinates.group, it.coordinates.module) } - .mapValues { (id, deps) -> - val versions = deps.groupBy { Version(it.coordinates.version) } - .mapValues { (version, deps) -> - val componentId = ModuleVersionId(id, version) + .filterNot { it.repository == null || it.repository !in repositories } + .groupBy { ModuleId(it.id.group, it.id.module) } + .mapValues { (_, deps) -> + val byVersion = deps.groupBy { it.id } + .mapValues { (componentId, deps) -> val dep = MergedDependency( id = componentId, - repositories = deps.mapNotNull { repositories[it.repository] } + repositories = deps.mapNotNull { repositories[it.repository] }.distinct() ) val component = verificationComponents[componentId] ?: verifyComponentFilesInCache(config, componentId) @@ -93,7 +90,7 @@ fun processDependencies(config: Config): Env { maybeDownloadMavenPom(config.logger, component, dep.repositories, gradleModule) } val ivyArtifact = ivyCache.getOrPut(componentId) { - maybeDownloadIvyDescriptor(config.logger, component, dep.repositories, gradleModule) + maybeDownloadIvyDescriptor(config.logger, component, dep.repositories) } val files = buildMap { @@ -104,7 +101,7 @@ fun processDependencies(config: Config): Env { artifact.name, ArtifactFile( urls = dep.repositories.flatMap { repo -> - artifactUrls(componentId, artifact.name, repo, gradleModule) + artifactUrls(config.logger, componentId, artifact.name, repo, gradleModule) }.distinct(), hash = artifact.checksums.first().toSri() ) @@ -114,8 +111,9 @@ fun processDependencies(config: Config): Env { ArtifactSet(files) } + .mapKeys { Version(it.key.version) } .toSortedMap(Version.Comparator.reversed()) - Module(versions) + Module(byVersion) } .toSortedMap(compareBy(ModuleId::toString)) } @@ -134,9 +132,9 @@ private fun readDependencyGraph(config: Config): List { private fun verifyComponentFilesInCache( config: Config, - id: ModuleVersionId, + id: DependencyCoordinates, ): Component? { - val cacheDir = with(id) { config.gradleHome.resolve("caches/modules-2/files-2.1/$group/$name/$version") } + val cacheDir = with(id) { config.gradleHome.resolve("caches/modules-2/files-2.1/$group/$module/$version") } if (!cacheDir.exists()) { return null } @@ -149,17 +147,17 @@ private fun verifyComponentFilesInCache( private fun verifyComponentFilesInTestRepository( config: Config, - id: ModuleVersionId + id: DependencyCoordinates ): Component? { if (m2 == null) return null val dir = with(id) { - File(URI.create(m2)).resolve("${group.replace(".", "/")}/$name/$version") + File(URI.create(m2)).resolve("${group.replace(".", "/")}/$module/$version") } if (!dir.exists()) { config.logger.log("$id: not found in m2 repository; tried $dir") return null } - val verifications = dir.walk().filter { it.isFile && it.name.startsWith(id.name) }.map { f -> + val verifications = dir.walk().filter { it.isFile && it.name.startsWith(id.module) }.map { f -> ArtifactMetadata( f.name, sha256 = Sha256(f.sha256()) @@ -175,7 +173,7 @@ private fun maybeDownloadGradleModule( repos: List ): ArtifactDownload>? { if (component.artifacts.none { it.name.endsWith(".module") }) return null - val filename = with(component.id) { "$name-$version.module" } + val filename = with(component.id) { "$module-$version.module" } return maybeDownloadArtifact(logger, component.id, filename, repos)?.let { artifact -> try { ArtifactDownload( @@ -199,12 +197,12 @@ private fun maybeDownloadMavenPom( if (component.artifacts.any { it.name.endsWith(".pom") }) return null val pomRepos = repos.filter { "mavenPom" in it.metadataSources } if (pomRepos.isEmpty()) return null - val filename = with(component.id) { "$name-$version.pom" } + val filename = with(component.id) { "$module-$version.pom" } return maybeDownloadArtifact(logger, component.id, filename, pomRepos)?.let { artifact -> filename to ArtifactFile( urls = pomRepos.flatMap { repo -> - artifactUrls(component.id, filename, repo, gradleModule) + artifactUrls(logger, component.id, filename, repo, gradleModule) }.distinct(), hash = artifact.hash.toSri() ) @@ -215,28 +213,52 @@ private fun maybeDownloadIvyDescriptor( logger: Logger, component: Component, repos: List, - gradleModule: GradleModule? ): Pair? { - if (component.artifacts.any { it.name == "ivy.xml" }) return null val ivyRepos = repos.filter { "ivyDescriptor" in it.metadataSources } if (ivyRepos.isEmpty()) return null - return maybeDownloadArtifact(logger, component.id, "ivy.xml", ivyRepos)?.let { artifact -> - "ivy.xml" to ArtifactFile( - urls = ivyRepos.flatMap { repo -> - artifactUrls(component.id, "ivy.xml", repo, gradleModule) - }.distinct(), - hash = artifact.hash.toSri() - ) + + val urls = ivyRepos + .flatMap { repo -> + val attributes = attributes(component.id, repo) + repo.metadataResources.mapNotNull { fill(it, attributes).takeIf(::isUrlComplete) } + } + .filter { url -> + component.artifacts.none { url.substringAfterLast('/') == it.name } + } + + var artifact: ArtifactDownload? = null + + for (url in urls) { + try { + val source = HashingSource.sha256(URL(url).openStream().source()) + val text = source.buffer().readUtf8() + val hash = source.hash + artifact = ArtifactDownload(text, url, Sha256(hash.hex())) + break + } catch (e: IOException) { + // Pass + } } + + if (artifact == null) { + logger.debug("ivy descriptor not found in urls: $urls") + return null + } + return artifact.artifact to ArtifactFile( + urls = urls, + hash = artifact.hash.toSri() + ) } private fun maybeDownloadArtifact( logger: Logger, - id: ModuleVersionId, + id: DependencyCoordinates, filename: String, repos: List ): ArtifactDownload? { - val urls = repos.flatMap { artifactUrls(id, filename, it, null)} + val urls = repos.flatMap { artifactUrls(logger, id, filename, it, null)} + + logger.debug("artifact $filename: $urls") for (url in urls) { try { @@ -270,10 +292,11 @@ private fun Checksum.toSri(): String { } private fun artifactUrls( - id: ModuleVersionId, + logger: Logger, + id: DependencyCoordinates, filename: String, repository: Repository, - module: GradleModule? + module: GradleModule?, ): List { val groupAsPath = id.group.replace(".", "/") @@ -286,8 +309,8 @@ private fun artifactUrls( val attributes = mutableMapOf( "organisation" to if (repository.m2Compatible) groupAsPath else id.group, - "module" to id.name, - "revision" to id.version.toString(), + "module" to id.module, + "revision" to id.version, ) + fileAttributes(repoFilename, id.version) val resources = when (attributes["ext"]) { @@ -299,7 +322,7 @@ private fun artifactUrls( repository.artifactResources } else -> repository.artifactResources - } + }.map { it.replaceFirst("-[revision]", "-${id.artifactVersion}") } val urls = mutableListOf() @@ -309,10 +332,12 @@ private fun artifactUrls( } if (location.none { it == '[' || it == ']' }) { urls.add(location) + } else { + logger.warn("failed to construct artifact URL: $location") } } - return urls + return urls.distinct() } private val optionalRegex = Regex("\\(([^)]+)\\)") @@ -328,8 +353,16 @@ private fun fill(template: String, attributes: Map): String { } } +private fun isUrlComplete(url: String): Boolean = !url.contains("[") + +private fun attributes(id: DependencyCoordinates, repository: Repository): Map = buildMap { + put("organisation", if (repository.m2Compatible) id.group.replace(".", "/") else id.group) + put("module", id.module) + put("revision", id.version) +} + // Gradle persists artifacts with the Maven artifact pattern, which may not match the repository's pattern. -private fun fileAttributes(file: String, version: Version): Map { +private fun fileAttributes(file: String, version: String): Map { val parts = Regex("(.+)-$version(-([^.]+))?(\\.(.+))?").matchEntire(file) ?: return emptyMap() val (artifact, _, classifier, _, ext) = parts.destructured @@ -342,7 +375,7 @@ private fun fileAttributes(file: String, version: Version): Map } private data class MergedDependency( - val id: ModuleVersionId, + val id: DependencyCoordinates, val repositories: List ) diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/env/Env.kt b/app/src/main/kotlin/org/nixos/gradle2nix/env/Env.kt index 414215b..2176a31 100644 --- a/app/src/main/kotlin/org/nixos/gradle2nix/env/Env.kt +++ b/app/src/main/kotlin/org/nixos/gradle2nix/env/Env.kt @@ -1,6 +1,5 @@ package org.nixos.gradle2nix.env -import java.util.concurrent.ConcurrentHashMap import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable import kotlinx.serialization.SerializationException @@ -9,8 +8,7 @@ import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder -import org.gradle.internal.impldep.com.google.common.collect.ImmutableMap -import org.gradle.internal.impldep.com.google.common.primitives.Longs +import org.nixos.gradle2nix.model.Version typealias Env = Map @@ -68,204 +66,3 @@ data class ModuleId( } } } - -@Serializable(ModuleVersionId.Serializer::class) -data class ModuleVersionId( - val moduleId: ModuleId, - val version: Version -) : Comparable { - constructor(group: String, name: String, version: Version) : this(ModuleId(group, name), version) - - val group: String get() = moduleId.group - val name: String get() = moduleId.name - - override fun compareTo(other: ModuleVersionId): Int = - compareValuesBy( - this, - other, - ModuleVersionId::moduleId, - ModuleVersionId::version - ) - - - override fun toString(): String = "$group:$name:$version" - - internal object Serializer : KSerializer { - override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor( - Version::class.qualifiedName!!, - PrimitiveKind.STRING - ) - - override fun serialize(encoder: Encoder, value: ModuleVersionId) { - encoder.encodeString(value.toString()) - } - - override fun deserialize(decoder: Decoder): ModuleVersionId { - val encoded = decoder.decodeString() - val parts = encoded.split(":") - if (parts.size != 3 || parts.any(String::isBlank)) { - throw SerializationException("invalid module version id: $encoded") - } - return ModuleVersionId( - moduleId = ModuleId(parts[0], parts[1]), - version = Version(parts[3]) - ) - } - } -} - -@Serializable(Version.Serializer::class) -class Version(val source: String, val parts: List, base: Version?) : Comparable { - - private val base: Version - val numericParts: List - - init { - this.base = base ?: this - this.numericParts = parts.map(Longs::tryParse) - } - - override fun compareTo(other: Version): Int = compare(this, other) - - override fun toString(): String = source - - override fun equals(other: Any?): Boolean = when { - other === this -> true - other == null || other !is Version -> false - else -> source == other.source - } - - override fun hashCode(): Int = source.hashCode() - - object Comparator : kotlin.Comparator { - override fun compare(o1: Version, o2: Version): Int = - Version.compare(o1, o2) - } - - internal object Serializer : KSerializer { - override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor( - Version::class.qualifiedName!!, - PrimitiveKind.STRING - ) - - override fun serialize(encoder: Encoder, value: Version) { - encoder.encodeString(value.source) - } - - override fun deserialize(decoder: Decoder): Version { - return Version(decoder.decodeString()) - } - } - - companion object { - private val SPECIAL_MEANINGS: Map = ImmutableMap.builderWithExpectedSize(7) - .put("dev", -1) - .put("rc", 1) - .put("snapshot", 2) - .put("final", 3).put("ga", 4).put("release", 5) - .put("sp", 6).build() - - private val cache = ConcurrentHashMap() - - // From org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionParser - operator fun invoke(original: String): Version = cache.getOrPut(original) { - val parts = mutableListOf() - var digit = false - var startPart = 0 - var pos = 0 - var endBase = 0 - var endBaseStr = 0 - while (pos < original.length) { - val ch = original[pos] - if (ch == '.' || ch == '_' || ch == '-' || ch == '+') { - parts.add(original.substring(startPart, pos)) - startPart = pos + 1 - digit = false - if (ch != '.' && endBaseStr == 0) { - endBase = parts.size - endBaseStr = pos - } - } else if (ch in '0'..'9') { - if (!digit && pos > startPart) { - if (endBaseStr == 0) { - endBase = parts.size + 1 - endBaseStr = pos - } - parts.add(original.substring(startPart, pos)) - startPart = pos - } - digit = true - } else { - if (digit) { - if (endBaseStr == 0) { - endBase = parts.size + 1 - endBaseStr = pos - } - parts.add(original.substring(startPart, pos)) - startPart = pos - } - digit = false - } - pos++ - } - if (pos > startPart) { - parts.add(original.substring(startPart, pos)) - } - var base: Version? = null - if (endBaseStr > 0) { - base = Version(original.substring(0, endBaseStr), parts.subList(0, endBase), null) - } - Version(original, parts, base) - } - - // From org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.StaticVersionComparator - private fun compare(version1: Version, version2: Version): Int { - if (version1 == version2) { - return 0 - } - - val parts1 = version1.parts - val parts2 = version2.parts - val numericParts1 = version1.numericParts - val numericParts2 = version2.numericParts - var lastIndex = -1 - - for (i in 0..<(minOf(parts1.size, parts2.size))) { - lastIndex = i - - val part1 = parts1[i] - val part2 = parts2[i] - - val numericPart1 = numericParts1[i] - val numericPart2 = numericParts2[i] - - when { - part1 == part2 -> continue - numericPart1 != null && numericPart2 == null -> return 1 - numericPart2 != null && numericPart1 == null -> return -1 - numericPart1 != null && numericPart2 != null -> { - val result = numericPart1.compareTo(numericPart2) - if (result == 0) continue - return result - } - else -> { - // both are strings, we compare them taking into account special meaning - val sm1 = SPECIAL_MEANINGS[part1.lowercase()] - val sm2 = SPECIAL_MEANINGS[part2.lowercase()] - if (sm1 != null) return sm1 - (sm2 ?: 0) - if (sm2 != null) return -sm2 - return part1.compareTo(part2) - } - } - } - if (lastIndex < parts1.size) { - return if (numericParts1[lastIndex] == null) -1 else 1 - } - if (lastIndex < parts2.size) { - return if (numericParts2[lastIndex] == null) 1 else -1 - } - - return 0 - } - } -} diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/VerificationMetadata.kt b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/VerificationMetadata.kt index 54b8c23..3bd95d9 100644 --- a/app/src/main/kotlin/org/nixos/gradle2nix/metadata/VerificationMetadata.kt +++ b/app/src/main/kotlin/org/nixos/gradle2nix/metadata/VerificationMetadata.kt @@ -9,8 +9,7 @@ import nl.adaptivity.xmlutil.serialization.XmlElement import nl.adaptivity.xmlutil.serialization.XmlSerialName import nl.adaptivity.xmlutil.xmlStreaming import org.nixos.gradle2nix.Logger -import org.nixos.gradle2nix.env.ModuleVersionId -import org.nixos.gradle2nix.env.Version +import org.nixos.gradle2nix.model.DependencyCoordinates sealed interface Coordinates { val group: String? @@ -104,15 +103,17 @@ data class Artifact( data class Component( val group: String, val name: String, - val version: Version, + val version: String, + val timestamp: String? = null, val artifacts: List = emptyList(), ) { - val id: ModuleVersionId get() = ModuleVersionId(group, name, version) + val id: DependencyCoordinates get() = DependencyCoordinates(group, name, version, timestamp) - constructor(id: ModuleVersionId, artifacts: List) : this( + constructor(id: DependencyCoordinates, artifacts: List) : this( id.group, - id.name, + id.module, id.version, + id.timestamp, artifacts ) } diff --git a/fixtures/golden/dependency/snapshot-redirect.groovy.json b/fixtures/golden/dependency/snapshot-redirect.groovy.json index d3f7334..d4f9c6c 100644 --- a/fixtures/golden/dependency/snapshot-redirect.groovy.json +++ b/fixtures/golden/dependency/snapshot-redirect.groovy.json @@ -3,13 +3,13 @@ "-SNAPSHOT": { "packr--SNAPSHOT.jar": { "urls": [ - "https://jitpack.io/com/github/anuken/packr/-SNAPSHOT/packr--SNAPSHOT.jar" + "https://jitpack.io/com/github/anuken/packr/-SNAPSHOT/packr--packr-1.2-g034efe5-114.jar" ], "hash": "sha256-XrfVZLc7efr2n3Bz6mOw8DkRI0T8rU8B/MKUMVDl71w=" }, "packr--SNAPSHOT.pom": { "urls": [ - "https://jitpack.io/com/github/anuken/packr/-SNAPSHOT/packr--SNAPSHOT.pom" + "https://jitpack.io/com/github/anuken/packr/-SNAPSHOT/packr--packr-1.2-g034efe5-114.pom" ], "hash": "sha256-xP28J7blX1IzuJxD4u/wy1ZbwAT5RAajBcpBWs1fAxU=" } diff --git a/fixtures/golden/plugin/resolves-from-default-repo.groovy.json b/fixtures/golden/plugin/resolves-from-default-repo.groovy.json index a1243bf..039ae71 100644 --- a/fixtures/golden/plugin/resolves-from-default-repo.groovy.json +++ b/fixtures/golden/plugin/resolves-from-default-repo.groovy.json @@ -3,15 +3,15 @@ "5.6.0": { "jna-5.6.0.jar": { "urls": [ - "https://plugins.gradle.org/m2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.jar", - "https://repo.maven.apache.org/maven2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.jar" + "https://repo.maven.apache.org/maven2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.jar", + "https://plugins.gradle.org/m2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.jar" ], "hash": "sha256-VVfiNaiqL5dm1dxgnWeUjyqIMsLXls6p7x1svgs7fq8=" }, "jna-5.6.0.pom": { "urls": [ - "https://plugins.gradle.org/m2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.pom", - "https://repo.maven.apache.org/maven2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.pom" + "https://repo.maven.apache.org/maven2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.pom", + "https://plugins.gradle.org/m2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.pom" ], "hash": "sha256-X+gbAlWXjyRhbTexBgi3lJil8wc+HZsgONhzaoMfJgg=" } @@ -21,15 +21,15 @@ "1.0.20200330": { "trove4j-1.0.20200330.jar": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.jar", - "https://repo.maven.apache.org/maven2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.jar" + "https://repo.maven.apache.org/maven2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.jar", + "https://plugins.gradle.org/m2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.jar" ], "hash": "sha256-xf1yW/+rUYRr88d9sTg8YKquv+G3/i8A0j/ht98KQ50=" }, "trove4j-1.0.20200330.pom": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.pom", - "https://repo.maven.apache.org/maven2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.pom" + "https://repo.maven.apache.org/maven2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.pom", + "https://plugins.gradle.org/m2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.pom" ], "hash": "sha256-h3IcuqZaPJfYsbqdIHhA8WTJ/jh1n8nqEP/iZWX40+k=" } @@ -97,15 +97,15 @@ "1.7.21": { "kotlin-compiler-embeddable-1.7.21.jar": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.jar", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.jar" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.jar", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.jar" ], "hash": "sha256-Ty5JK8x5XgaA4/h67qGtrp8wbK9SBAuUpvoPiP2skvk=" }, "kotlin-compiler-embeddable-1.7.21.pom": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.pom", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.pom" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.pom", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.pom" ], "hash": "sha256-CwIzMip2MO/eEzUmjkYSPw1tNjg5gg/TfE7Lbv+njjs=" } @@ -147,15 +147,15 @@ "1.7.21": { "kotlin-daemon-embeddable-1.7.21.jar": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.jar", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.jar" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.jar", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.jar" ], "hash": "sha256-A+bwJUNSJIlOSe5e2EfLCwtKh540z6uQ1wzakmKnV00=" }, "kotlin-daemon-embeddable-1.7.21.pom": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.pom", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.pom" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.pom", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.pom" ], "hash": "sha256-vB3pwgh7ouTlQQF6i66PQF7IAKGK5MJH6R8rVedh5kk=" } @@ -371,15 +371,15 @@ "1.7.21": { "kotlin-scripting-common-1.7.21.jar": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.jar", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.jar" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.jar", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.jar" ], "hash": "sha256-0ZLMLNlDFecijrkTZqNpdmpoIrPOvKwUwR1MSXM2y6Q=" }, "kotlin-scripting-common-1.7.21.pom": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.pom", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.pom" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.pom", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.pom" ], "hash": "sha256-2xzYRWGPDLQXOK3H72jZ+NIjZ1sFg+NbsMCEA30AWe4=" } @@ -389,15 +389,15 @@ "1.7.21": { "kotlin-scripting-compiler-embeddable-1.7.21.jar": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.jar", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.jar" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.jar", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.jar" ], "hash": "sha256-qu9jHwICEl2ZHZgjRxn4ZK1anW40m/DtRGsTd9gXGKE=" }, "kotlin-scripting-compiler-embeddable-1.7.21.pom": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.pom", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.pom" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.pom", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.pom" ], "hash": "sha256-xHXL2+0BepcMD9y46qu1UNc9E6T+a4e3efxM9S148JM=" } @@ -407,15 +407,15 @@ "1.7.21": { "kotlin-scripting-compiler-impl-embeddable-1.7.21.jar": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.jar", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.jar" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.jar", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.jar" ], "hash": "sha256-ZOK9uuvzgJSzwh5nCX5Qe4NoTaQTi6h6CwmhMgOXVCg=" }, "kotlin-scripting-compiler-impl-embeddable-1.7.21.pom": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.pom", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.pom" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.pom", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.pom" ], "hash": "sha256-5c0+HEj+qhC1YVqidOFh5/dcFijcJhZ1ALZ0b4gfweM=" } @@ -425,15 +425,15 @@ "1.7.21": { "kotlin-scripting-jvm-1.7.21.jar": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.jar", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.jar" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.jar", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.jar" ], "hash": "sha256-Uz441a1oFCoFE0HyK8cO113IUGSxk3rPBRN1XMPwSF4=" }, "kotlin-scripting-jvm-1.7.21.pom": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.pom", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.pom" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.pom", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.pom" ], "hash": "sha256-cnwtOnluoiOWPu7P7kHvKygsVbZ+V8O0mgFwpMSbfGE=" } diff --git a/fixtures/golden/plugin/resolves-from-default-repo.kotlin.json b/fixtures/golden/plugin/resolves-from-default-repo.kotlin.json index a1243bf..039ae71 100644 --- a/fixtures/golden/plugin/resolves-from-default-repo.kotlin.json +++ b/fixtures/golden/plugin/resolves-from-default-repo.kotlin.json @@ -3,15 +3,15 @@ "5.6.0": { "jna-5.6.0.jar": { "urls": [ - "https://plugins.gradle.org/m2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.jar", - "https://repo.maven.apache.org/maven2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.jar" + "https://repo.maven.apache.org/maven2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.jar", + "https://plugins.gradle.org/m2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.jar" ], "hash": "sha256-VVfiNaiqL5dm1dxgnWeUjyqIMsLXls6p7x1svgs7fq8=" }, "jna-5.6.0.pom": { "urls": [ - "https://plugins.gradle.org/m2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.pom", - "https://repo.maven.apache.org/maven2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.pom" + "https://repo.maven.apache.org/maven2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.pom", + "https://plugins.gradle.org/m2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.pom" ], "hash": "sha256-X+gbAlWXjyRhbTexBgi3lJil8wc+HZsgONhzaoMfJgg=" } @@ -21,15 +21,15 @@ "1.0.20200330": { "trove4j-1.0.20200330.jar": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.jar", - "https://repo.maven.apache.org/maven2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.jar" + "https://repo.maven.apache.org/maven2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.jar", + "https://plugins.gradle.org/m2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.jar" ], "hash": "sha256-xf1yW/+rUYRr88d9sTg8YKquv+G3/i8A0j/ht98KQ50=" }, "trove4j-1.0.20200330.pom": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.pom", - "https://repo.maven.apache.org/maven2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.pom" + "https://repo.maven.apache.org/maven2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.pom", + "https://plugins.gradle.org/m2/org/jetbrains/intellij/deps/trove4j/1.0.20200330/trove4j-1.0.20200330.pom" ], "hash": "sha256-h3IcuqZaPJfYsbqdIHhA8WTJ/jh1n8nqEP/iZWX40+k=" } @@ -97,15 +97,15 @@ "1.7.21": { "kotlin-compiler-embeddable-1.7.21.jar": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.jar", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.jar" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.jar", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.jar" ], "hash": "sha256-Ty5JK8x5XgaA4/h67qGtrp8wbK9SBAuUpvoPiP2skvk=" }, "kotlin-compiler-embeddable-1.7.21.pom": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.pom", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.pom" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.pom", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.21/kotlin-compiler-embeddable-1.7.21.pom" ], "hash": "sha256-CwIzMip2MO/eEzUmjkYSPw1tNjg5gg/TfE7Lbv+njjs=" } @@ -147,15 +147,15 @@ "1.7.21": { "kotlin-daemon-embeddable-1.7.21.jar": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.jar", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.jar" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.jar", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.jar" ], "hash": "sha256-A+bwJUNSJIlOSe5e2EfLCwtKh540z6uQ1wzakmKnV00=" }, "kotlin-daemon-embeddable-1.7.21.pom": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.pom", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.pom" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.pom", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.21/kotlin-daemon-embeddable-1.7.21.pom" ], "hash": "sha256-vB3pwgh7ouTlQQF6i66PQF7IAKGK5MJH6R8rVedh5kk=" } @@ -371,15 +371,15 @@ "1.7.21": { "kotlin-scripting-common-1.7.21.jar": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.jar", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.jar" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.jar", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.jar" ], "hash": "sha256-0ZLMLNlDFecijrkTZqNpdmpoIrPOvKwUwR1MSXM2y6Q=" }, "kotlin-scripting-common-1.7.21.pom": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.pom", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.pom" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.pom", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.21/kotlin-scripting-common-1.7.21.pom" ], "hash": "sha256-2xzYRWGPDLQXOK3H72jZ+NIjZ1sFg+NbsMCEA30AWe4=" } @@ -389,15 +389,15 @@ "1.7.21": { "kotlin-scripting-compiler-embeddable-1.7.21.jar": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.jar", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.jar" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.jar", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.jar" ], "hash": "sha256-qu9jHwICEl2ZHZgjRxn4ZK1anW40m/DtRGsTd9gXGKE=" }, "kotlin-scripting-compiler-embeddable-1.7.21.pom": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.pom", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.pom" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.pom", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.21/kotlin-scripting-compiler-embeddable-1.7.21.pom" ], "hash": "sha256-xHXL2+0BepcMD9y46qu1UNc9E6T+a4e3efxM9S148JM=" } @@ -407,15 +407,15 @@ "1.7.21": { "kotlin-scripting-compiler-impl-embeddable-1.7.21.jar": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.jar", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.jar" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.jar", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.jar" ], "hash": "sha256-ZOK9uuvzgJSzwh5nCX5Qe4NoTaQTi6h6CwmhMgOXVCg=" }, "kotlin-scripting-compiler-impl-embeddable-1.7.21.pom": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.pom", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.pom" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.pom", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.21/kotlin-scripting-compiler-impl-embeddable-1.7.21.pom" ], "hash": "sha256-5c0+HEj+qhC1YVqidOFh5/dcFijcJhZ1ALZ0b4gfweM=" } @@ -425,15 +425,15 @@ "1.7.21": { "kotlin-scripting-jvm-1.7.21.jar": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.jar", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.jar" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.jar", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.jar" ], "hash": "sha256-Uz441a1oFCoFE0HyK8cO113IUGSxk3rPBRN1XMPwSF4=" }, "kotlin-scripting-jvm-1.7.21.pom": { "urls": [ - "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.pom", - "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.pom" + "https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.pom", + "https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.21/kotlin-scripting-jvm-1.7.21.pom" ], "hash": "sha256-cnwtOnluoiOWPu7P7kHvKygsVbZ+V8O0mgFwpMSbfGE=" } diff --git a/model/src/main/kotlin/org/nixos/gradle2nix/model/DependencyCoordinates.kt b/model/src/main/kotlin/org/nixos/gradle2nix/model/DependencyCoordinates.kt index 72de287..b5bc83f 100644 --- a/model/src/main/kotlin/org/nixos/gradle2nix/model/DependencyCoordinates.kt +++ b/model/src/main/kotlin/org/nixos/gradle2nix/model/DependencyCoordinates.kt @@ -1,26 +1,53 @@ package org.nixos.gradle2nix.model +import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder -@Serializable +@Serializable(DependencyCoordinates.Serializer::class) data class DependencyCoordinates( val group: String, val module: String, val version: String, val timestamp: String? = null -) { +) : Comparable { + override fun toString(): String = if (timestamp != null) { "$group:$module:$version:$timestamp" } else { "$group:$module:$version" } - val isSnapshot: Boolean get() = timestamp != null - val moduleVersion: String get() = version val artifactVersion: String get() = timestamp?.let { version.replace("SNAPSHOT", it) } ?: version + override fun compareTo(other: DependencyCoordinates): Int = comparator.compare(this, other) + + object Serializer : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor( + DependencyCoordinates::class.qualifiedName!!, + PrimitiveKind.STRING + ) + + override fun deserialize(decoder: Decoder): DependencyCoordinates { + val encoded = decoder.decodeString() + return parse(encoded) + } + + override fun serialize(encoder: Encoder, value: DependencyCoordinates) { + encoder.encodeString(value.toString()) + } + } + companion object { + val comparator = compareBy { it.group } + .thenBy { it.module } + .thenByDescending { it.artifactVersion } + fun parse(id: String): DependencyCoordinates { val parts = id.split(":") return when (parts.size) { diff --git a/model/src/main/kotlin/org/nixos/gradle2nix/model/ResolvedConfiguration.kt b/model/src/main/kotlin/org/nixos/gradle2nix/model/ResolvedConfiguration.kt index 829f049..72ec576 100644 --- a/model/src/main/kotlin/org/nixos/gradle2nix/model/ResolvedConfiguration.kt +++ b/model/src/main/kotlin/org/nixos/gradle2nix/model/ResolvedConfiguration.kt @@ -13,7 +13,7 @@ data class ResolvedConfiguration( allDependencies.add(component) } - fun hasDependency(componentId: String): Boolean { + fun hasDependency(componentId: DependencyCoordinates): Boolean { return allDependencies.any { it.id == componentId } } } diff --git a/model/src/main/kotlin/org/nixos/gradle2nix/model/ResolvedDependency.kt b/model/src/main/kotlin/org/nixos/gradle2nix/model/ResolvedDependency.kt index dcb2375..f219359 100644 --- a/model/src/main/kotlin/org/nixos/gradle2nix/model/ResolvedDependency.kt +++ b/model/src/main/kotlin/org/nixos/gradle2nix/model/ResolvedDependency.kt @@ -4,10 +4,9 @@ import kotlinx.serialization.Serializable @Serializable data class ResolvedDependency( - val id: String, + val id: DependencyCoordinates, val source: DependencySource, val direct: Boolean, - val coordinates: DependencyCoordinates, val repository: String?, val dependencies: List = emptyList(), ) diff --git a/model/src/main/kotlin/org/nixos/gradle2nix/model/Version.kt b/model/src/main/kotlin/org/nixos/gradle2nix/model/Version.kt new file mode 100644 index 0000000..8219268 --- /dev/null +++ b/model/src/main/kotlin/org/nixos/gradle2nix/model/Version.kt @@ -0,0 +1,172 @@ +package org.nixos.gradle2nix.model + +import java.util.concurrent.ConcurrentHashMap +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + + +@Serializable(Version.Serializer::class) +class Version(val source: String, val parts: List, base: Version?) : Comparable { + + private val base: Version + val numericParts: List + + init { + this.base = base ?: this + this.numericParts = parts.map { + try { it.toLong() } catch (e: NumberFormatException) { null } + } + } + + override fun compareTo(other: Version): Int = compare(this, other) + + override fun toString(): String = source + + override fun equals(other: Any?): Boolean = when { + other === this -> true + other == null || other !is Version -> false + else -> source == other.source + } + + override fun hashCode(): Int = source.hashCode() + + object Comparator : kotlin.Comparator { + override fun compare(o1: Version, o2: Version): Int = + Version.compare(o1, o2) + } + + internal object Serializer : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor( + Version::class.qualifiedName!!, + PrimitiveKind.STRING + ) + + override fun serialize(encoder: Encoder, value: Version) { + encoder.encodeString(value.source) + } + + override fun deserialize(decoder: Decoder): Version { + return Version(decoder.decodeString()) + } + } + + companion object { + private val SPECIAL_MEANINGS: Map = mapOf( + "dev" to -1, + "rc" to 1, + "snapshot" to 2, + "final" to 3, + "ga" to 4, + "release" to 5, + "sp" to 6 + ) + + private val cache = ConcurrentHashMap() + + // From org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionParser + operator fun invoke(original: String): Version = cache.getOrPut(original) { + val parts = mutableListOf() + var digit = false + var startPart = 0 + var pos = 0 + var endBase = 0 + var endBaseStr = 0 + while (pos < original.length) { + val ch = original[pos] + if (ch == '.' || ch == '_' || ch == '-' || ch == '+') { + parts.add(original.substring(startPart, pos)) + startPart = pos + 1 + digit = false + if (ch != '.' && endBaseStr == 0) { + endBase = parts.size + endBaseStr = pos + } + } else if (ch in '0'..'9') { + if (!digit && pos > startPart) { + if (endBaseStr == 0) { + endBase = parts.size + 1 + endBaseStr = pos + } + parts.add(original.substring(startPart, pos)) + startPart = pos + } + digit = true + } else { + if (digit) { + if (endBaseStr == 0) { + endBase = parts.size + 1 + endBaseStr = pos + } + parts.add(original.substring(startPart, pos)) + startPart = pos + } + digit = false + } + pos++ + } + if (pos > startPart) { + parts.add(original.substring(startPart, pos)) + } + var base: Version? = null + if (endBaseStr > 0) { + base = Version(original.substring(0, endBaseStr), parts.subList(0, endBase), null) + } + Version(original, parts, base) + } + + // From org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.StaticVersionComparator + private fun compare(version1: Version, version2: Version): Int { + if (version1 == version2) { + return 0 + } + + val parts1 = version1.parts + val parts2 = version2.parts + val numericParts1 = version1.numericParts + val numericParts2 = version2.numericParts + var lastIndex = -1 + + for (i in 0..<(minOf(parts1.size, parts2.size))) { + lastIndex = i + + val part1 = parts1[i] + val part2 = parts2[i] + + val numericPart1 = numericParts1[i] + val numericPart2 = numericParts2[i] + + when { + part1 == part2 -> continue + numericPart1 != null && numericPart2 == null -> return 1 + numericPart2 != null && numericPart1 == null -> return -1 + numericPart1 != null && numericPart2 != null -> { + val result = numericPart1.compareTo(numericPart2) + if (result == 0) continue + return result + } + else -> { + // both are strings, we compare them taking into account special meaning + val sm1 = SPECIAL_MEANINGS[part1.lowercase()] + val sm2 = SPECIAL_MEANINGS[part2.lowercase()] + if (sm1 != null) return sm1 - (sm2 ?: 0) + if (sm2 != null) return -sm2 + return part1.compareTo(part2) + } + } + } + if (lastIndex < parts1.size) { + return if (numericParts1[lastIndex] == null) -1 else 1 + } + if (lastIndex < parts2.size) { + return if (numericParts2[lastIndex] == null) 1 else -1 + } + + return 0 + } + } +} diff --git a/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/extractor/DependencyExtractor.kt b/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/extractor/DependencyExtractor.kt index 18ec2b6..c9ddea7 100644 --- a/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/extractor/DependencyExtractor.kt +++ b/plugin/src/main/kotlin/org/nixos/gradle2nix/dependencygraph/extractor/DependencyExtractor.kt @@ -205,17 +205,19 @@ abstract class DependencyExtractor : val resolvedConfiguration = ResolvedConfiguration(source, details.configurationName, repositories) for (directDependency in getResolvedDependencies(rootComponent)) { - val moduleComponentId = directDependency.id as? ModuleComponentIdentifier ?: continue - val directDep = createComponentNode( - moduleComponentId, - source, - true, - directDependency, - result.getRepositoryId(directDependency) - ) - resolvedConfiguration.addDependency(directDep) + val coordinates = (directDependency.id as? ModuleComponentIdentifier)?.let(::coordinates) + if (coordinates != null) { + val directDep = createComponentNode( + coordinates, + source, + true, + directDependency, + result.getRepositoryId(directDependency) + ) + resolvedConfiguration.addDependency(directDep) - walkComponentDependencies(result, directDependency, directDep.source, resolvedConfiguration) + walkComponentDependencies(result, directDependency, directDep.source, resolvedConfiguration) + } } resolvedConfigurations.add(resolvedConfiguration) @@ -232,19 +234,17 @@ abstract class DependencyExtractor : val dependencyComponents = getResolvedDependencies(component) for (dependencyComponent in dependencyComponents) { - if (!resolvedConfiguration.hasDependency(componentId(dependencyComponent))) { - val moduleComponentId = dependencyComponent.id as? ModuleComponentIdentifier - if (moduleComponentId != null) { - val dependencyNode = createComponentNode( - moduleComponentId, - componentSource, - direct, - dependencyComponent, - result.getRepositoryId(component) - ) - resolvedConfiguration.addDependency(dependencyNode) - } - + val coordinates = (dependencyComponent.id as? ModuleComponentIdentifier)?.let(::coordinates) + ?: continue + if (!resolvedConfiguration.hasDependency(coordinates)) { + val dependencyNode = createComponentNode( + coordinates, + componentSource, + direct, + dependencyComponent, + result.getRepositoryId(component) + ) + resolvedConfiguration.addDependency(dependencyNode) walkComponentDependencies(result, dependencyComponent, componentSource, resolvedConfiguration) } } @@ -271,7 +271,7 @@ abstract class DependencyExtractor : } private fun createComponentNode( - componentId: ModuleComponentIdentifier, + coordinates: DependencyCoordinates, source: DependencySource, direct: Boolean, component: ResolvedComponentResult, @@ -279,12 +279,10 @@ abstract class DependencyExtractor : ): ResolvedDependency { val componentDependencies = component.dependencies.filterIsInstance().map { componentId(it.selected) } - val coordinates = coordinates(componentId) return ResolvedDependency( - componentId.displayName, + coordinates, source, direct, - coordinates, repositoryId, componentDependencies, ) @@ -303,16 +301,6 @@ abstract class DependencyExtractor : ) } - private fun artifactType(type: Class): ResolvedArtifact.Type? { - return when (type) { - SourcesArtifact::class.java -> ResolvedArtifact.Type.SOURCES - JavadocArtifact::class.java -> ResolvedArtifact.Type.JAVADOC - IvyDescriptorArtifact::class.java -> ResolvedArtifact.Type.IVY_DESCRIPTOR - MavenPomArtifact::class.java -> ResolvedArtifact.Type.MAVEN_POM - else -> null - } - } - private fun writeDependencyGraph() { val outputDirectory = getOutputDir() outputDirectory.mkdirs()