Gradle, js, npm: fix resolving transitive npm dependencies using yarn.lock

- already visited transitive npm dependencies should be stored in parent dependencies
- child NpmDependency should search resolved project data in parent NpmDependencies
This commit is contained in:
Sergey Rostov
2019-06-04 13:54:18 +03:00
parent 465a47a194
commit 1c0519b0a2
2 changed files with 24 additions and 14 deletions
@@ -31,6 +31,7 @@ data class NpmDependency(
override fun getGroup(): String? = org
internal var parent: NpmDependency? = null
internal val dependencies = mutableSetOf<NpmDependency>()
override fun resolve(transitive: Boolean): MutableSet<File> {
@@ -64,7 +65,9 @@ data class NpmDependency(
}
override fun resolve(): MutableSet<File> {
val npmPackage = resolveProject() ?: return mutableSetOf()
val npmPackage = parent?.resolveProject()
?: resolveProject()
?: return mutableSetOf()
return mutableSetOf(npmPackage.npmProject.resolve(key)!!)
}
@@ -86,7 +89,8 @@ data class NpmDependency(
return when (result) {
null -> null
is AlreadyInProgress -> null
is AlreadyResolved -> findIn(result.resolution) ?: error("Project hierarchy is already resolved in NPM without $this")
is AlreadyResolved -> findIn(result.resolution)
?: error("Project hierarchy is already resolved in NPM without $this")
is ResolvedNow -> findIn(result.resolution) ?: error("Cannot find $this after NPM project resolve")
}
}
@@ -42,29 +42,35 @@ abstract class YarnBasics : NpmApi {
val yarnLock = nodeWorkDir.resolve("yarn.lock")
if (yarnLock.isFile) {
val byKey = YarnLock.parse(yarnLock).entries.associateBy { it.key }
val visited = mutableSetOf<NpmDependency>()
val visited = mutableMapOf<NpmDependency, NpmDependency>()
fun resolveRecursively(src: NpmDependency): NpmDependency {
if (src in visited) return src
visited.add(src)
val copy = visited[src]
if (copy != null) {
src.dependencies.addAll(copy.dependencies)
return src
}
visited[src] = src
val key = YarnLock.key(src.key, src.version)
val deps = byKey[key]
if (deps != null) {
src.dependencies.addAll(deps.dependencies.map { dep ->
val scopedName = dep.scopedName
resolveRecursively(
NpmDependency(
src.project,
scopedName.scope,
scopedName.name,
dep.version ?: "*"
)
val child = NpmDependency(
src.project,
scopedName.scope,
scopedName.name,
dep.version ?: "*"
)
child.parent = src
resolveRecursively(child)
child
})
} else {
// todo: [WARN] cannot find $key in yarn.lock
error("Cannot find $key in yarn.lock")
}
return src