[Gradle, JS] Fix yarn.lock resolution in case of duplicated dependencies

^KT-42222 fixed
^KT-40986 fixed
^KT-39838 fixed
This commit is contained in:
Ilya Goncharov
2020-09-28 15:15:04 +03:00
parent 34b6003371
commit 024771028c
3 changed files with 44 additions and 24 deletions
@@ -19,12 +19,11 @@ fun versionToNpmRanges(version: String): Set<NpmRange> {
.visit(parser.rangeSet())!!
}
fun buildNpmVersion(
fun includedRange(
includedVersions: List<String>,
excludedVersions: List<String>,
includedWithCaret: Boolean = false
): String {
val includedRange: NpmRange? = try {
): NpmRange =
try {
includedVersions
.flatMap { versionToNpmRanges(it) }
.map { if (includedWithCaret) it.caretizeSingleVersion() else it }
@@ -33,13 +32,18 @@ fun buildNpmVersion(
requireNotNull(intersection) {
"Included versions have no intersection $includedVersions"
}
intersection!!
intersection
}
} catch (e: UnsupportedOperationException) {
throw InvalidUserDataException("No ranges for included versions $includedVersions")
}
includedRange!!
fun buildNpmVersion(
includedVersions: List<String>,
excludedVersions: List<String>,
includedWithCaret: Boolean = false
): String {
val includedRange: NpmRange = includedRange(includedVersions, includedWithCaret)
if (excludedVersions.isEmpty()) return includedRange.toString()
@@ -9,6 +9,7 @@ import com.google.gson.ExclusionStrategy
import com.google.gson.FieldAttributes
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import org.gradle.api.GradleException
import org.jetbrains.kotlin.gradle.internal.ensureParentDirsCreated
import java.io.File
@@ -126,7 +127,7 @@ fun packageJson(
npmDependencies.forEach {
val module = it.key
dependencies[it.key] = chooseVersion(dependencies[module], it.version)
dependencies[module] = chooseVersion(module, dependencies[module], it.version)
}
npmDependencies.forEach {
@@ -146,12 +147,19 @@ fun packageJson(
return packageJson
}
// TODO: real versions conflict resolution
private fun chooseVersion(oldVersion: String?, newVersion: String): String {
// https://yarnpkg.com/lang/en/docs/dependency-versions/#toc-x-ranges
if (oldVersion == "*") {
private fun chooseVersion(
module: String,
oldVersion: String?,
newVersion: String
): String {
if (oldVersion == null) {
return newVersion
}
return oldVersion ?: newVersion
return (includedRange(listOf(oldVersion)) intersect includedRange(listOf(newVersion)))?.toString()
?: throw GradleException(
"""
There is already declared version of '$module' with version '$oldVersion' which does not intersects with another declared version '${newVersion}'
""".trimIndent()
)
}
@@ -5,8 +5,10 @@
package org.jetbrains.kotlin.gradle.targets.js.yarn
import com.github.gundy.semver4j.SemVer
import org.gradle.api.GradleException
import org.jetbrains.kotlin.gradle.targets.js.npm.FILE_VERSION_PREFIX
import org.jetbrains.kotlin.gradle.targets.js.npm.includedRange
import org.jetbrains.kotlin.gradle.targets.js.npm.intersect
import java.io.File
internal class YarnEntryRegistry(private val lockFile: File) {
@@ -16,21 +18,27 @@ internal class YarnEntryRegistry(private val lockFile: File) {
fun find(packageKey: String, version: String): YarnLock.Entry {
val key = dependencyKey(packageKey, version)
var entry = entryMap[key]
val entry = entryMap[key]
if (entry == null && version == "*") {
val searchKey = dependencyKey(packageKey, "")
entry = entryMap.entries
.filter { it.key.startsWith(searchKey) }
.firstOrNull {
SemVer.satisfies(it.key.removePrefix(searchKey), "*")
if (entry != null) {
return entry
}
val versionRange = includedRange(listOf(version))
entryMap.entries
.firstOrNull { (_, entry) ->
if (entry.version == null) {
false
} else {
(versionRange intersect includedRange(listOf(entry.version))) != null
}
?.value
}
}
?.let { return it.value }
return checkNotNull(entry) {
throw GradleException(
"Cannot find $key in yarn.lock"
}
)
}
private val YarnLock.Entry.dependencyKey: String