Gradle, js, npm: remove hoisted gradle node modules. Split results collection from shared cache.
#KT-30530
This commit is contained in:
+3
-1
@@ -82,14 +82,16 @@ internal class ProcessedFilesCache(
|
|||||||
internal fun getOrCompute(
|
internal fun getOrCompute(
|
||||||
file: File,
|
file: File,
|
||||||
compute: () -> String?
|
compute: () -> String?
|
||||||
) {
|
): String? {
|
||||||
val hash = hasher.hash(file).toByteArray()
|
val hash = hasher.hash(file).toByteArray()
|
||||||
val old = old[hash]
|
val old = old[hash]
|
||||||
if (old != null) {
|
if (old != null) {
|
||||||
new[hash] = old
|
new[hash] = old
|
||||||
|
return old.target
|
||||||
} else {
|
} else {
|
||||||
val key = compute()
|
val key = compute()
|
||||||
new[hash] = Element(file.canonicalPath, key)
|
new[hash] = Element(file.canonicalPath, key)
|
||||||
|
return key
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ internal class GradleNodeModuleBuilder(
|
|||||||
val project: Project,
|
val project: Project,
|
||||||
val dependency: ResolvedDependency,
|
val dependency: ResolvedDependency,
|
||||||
val artifacts: Set<ResolvedArtifact>,
|
val artifacts: Set<ResolvedArtifact>,
|
||||||
val cache: GradleNodeModulesBuilder
|
val cache: GradleNodeModulesCache
|
||||||
) {
|
) {
|
||||||
var srcPackageJsonFile: File? = null
|
var srcPackageJsonFile: File? = null
|
||||||
val files = mutableListOf<File>()
|
val files = mutableListOf<File>()
|
||||||
|
|||||||
+14
-16
@@ -12,7 +12,7 @@ import org.gradle.api.artifacts.ResolvedDependency
|
|||||||
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
|
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
|
||||||
import org.jetbrains.kotlin.gradle.internal.ProcessedFilesCache
|
import org.jetbrains.kotlin.gradle.internal.ProcessedFilesCache
|
||||||
|
|
||||||
internal class GradleNodeModulesBuilder(val project: Project) : AutoCloseable {
|
internal class GradleNodeModulesCache(val project: Project) : AutoCloseable {
|
||||||
companion object {
|
companion object {
|
||||||
const val STATE_FILE_NAME = ".visited"
|
const val STATE_FILE_NAME = ".visited"
|
||||||
}
|
}
|
||||||
@@ -21,34 +21,28 @@ internal class GradleNodeModulesBuilder(val project: Project) : AutoCloseable {
|
|||||||
private val cache = ProcessedFilesCache(project, dir, STATE_FILE_NAME, "5")
|
private val cache = ProcessedFilesCache(project, dir, STATE_FILE_NAME, "5")
|
||||||
private val visited = mutableSetOf<ResolvedDependency>()
|
private val visited = mutableSetOf<ResolvedDependency>()
|
||||||
|
|
||||||
val modules
|
fun collectDependenciesFromConfiguration(configuration: Configuration, result: NpmProjectGradleDeps) {
|
||||||
get() = cache.targets.map {
|
|
||||||
GradleNodeModule(it, dir.resolve(it))
|
|
||||||
}
|
|
||||||
|
|
||||||
val projects = mutableSetOf<Project>()
|
|
||||||
|
|
||||||
fun visitConfiguration(configuration: Configuration) {
|
|
||||||
if (configuration.isCanBeResolved) {
|
if (configuration.isCanBeResolved) {
|
||||||
configuration.resolvedConfiguration.firstLevelModuleDependencies.forEach {
|
configuration.resolvedConfiguration.firstLevelModuleDependencies.forEach {
|
||||||
visitDependency(it)
|
visitDependency(it, result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun visitDependency(dependency: ResolvedDependency) {
|
private fun visitDependency(dependency: ResolvedDependency, result: NpmProjectGradleDeps) {
|
||||||
if (!visited.add(dependency)) return
|
if (!visited.add(dependency)) return
|
||||||
|
|
||||||
visitArtifacts(dependency, dependency.moduleArtifacts)
|
visitArtifacts(dependency, dependency.moduleArtifacts, result)
|
||||||
|
|
||||||
dependency.children.forEach {
|
dependency.children.forEach {
|
||||||
visitDependency(it)
|
visitDependency(it, result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun visitArtifacts(
|
private fun visitArtifacts(
|
||||||
dependency: ResolvedDependency,
|
dependency: ResolvedDependency,
|
||||||
artifacts: MutableSet<ResolvedArtifact>
|
artifacts: MutableSet<ResolvedArtifact>,
|
||||||
|
result: NpmProjectGradleDeps
|
||||||
) {
|
) {
|
||||||
val lazyDirName: String? by lazy {
|
val lazyDirName: String? by lazy {
|
||||||
val module = GradleNodeModuleBuilder(project, dependency, artifacts, this)
|
val module = GradleNodeModuleBuilder(project, dependency, artifacts, this)
|
||||||
@@ -62,11 +56,15 @@ internal class GradleNodeModulesBuilder(val project: Project) : AutoCloseable {
|
|||||||
val dependentProject = project.findProject(componentIdentifier.projectPath)
|
val dependentProject = project.findProject(componentIdentifier.projectPath)
|
||||||
?: error("Cannot find project ${componentIdentifier.projectPath}")
|
?: error("Cannot find project ${componentIdentifier.projectPath}")
|
||||||
|
|
||||||
projects.add(dependentProject)
|
result.internalModules.add(dependentProject)
|
||||||
} else {
|
} else {
|
||||||
cache.getOrCompute(artifact.file) {
|
val key = cache.getOrCompute(artifact.file) {
|
||||||
lazyDirName
|
lazyDirName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key != null) {
|
||||||
|
result.externalModules.add(GradleNodeModule(key, dir.resolve(key)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+6
-1
@@ -30,7 +30,12 @@ interface NpmApi {
|
|||||||
allWorkspaces: Collection<NpmResolver.NpmPackage>
|
allWorkspaces: Collection<NpmResolver.NpmPackage>
|
||||||
): Boolean = false
|
): Boolean = false
|
||||||
|
|
||||||
open fun shouldHoistGradleNodeModules(project: Project) = false
|
fun cleanProject(project: Project) {
|
||||||
|
val npmProject = project.npmProject
|
||||||
|
|
||||||
|
npmProject.nodeModulesDir.deleteRecursively()
|
||||||
|
npmProject.packageJsonFile.delete()
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun resolveOperationDescription(packageManagerTitle: String): String =
|
fun resolveOperationDescription(packageManagerTitle: String): String =
|
||||||
|
|||||||
+1
-6
@@ -33,13 +33,8 @@ open class NpmProject(
|
|||||||
private val parentModules: NpmProjectModules?
|
private val parentModules: NpmProjectModules?
|
||||||
get() = project.parent?.npmProject?.modules
|
get() = project.parent?.npmProject?.modules
|
||||||
|
|
||||||
val hoistGradleNodeModules: Boolean
|
|
||||||
get() = project.nodeJs.root.packageManager.shouldHoistGradleNodeModules(project)
|
|
||||||
|
|
||||||
val gradleNodeModulesDir: File
|
val gradleNodeModulesDir: File
|
||||||
get() =
|
get() = project.rootProject.npmProject.nodeModulesDir
|
||||||
if (hoistGradleNodeModules) project.rootProject.npmProject.nodeModulesDir
|
|
||||||
else nodeModulesDir
|
|
||||||
|
|
||||||
open fun compileOutput(compilationTask: Kotlin2JsCompile): File {
|
open fun compileOutput(compilationTask: Kotlin2JsCompile): File {
|
||||||
return compileOutputCopyDest?.resolve(compilationTask.outputFile.name) ?: compilationTask.outputFile
|
return compileOutputCopyDest?.resolve(compilationTask.outputFile.name) ?: compilationTask.outputFile
|
||||||
|
|||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.targets.js.npm
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
|
||||||
|
class NpmProjectGradleDeps {
|
||||||
|
val internalModules = mutableSetOf<Project>()
|
||||||
|
val externalModules = mutableSetOf<GradleNodeModule>()
|
||||||
|
}
|
||||||
+37
-46
@@ -34,7 +34,7 @@ import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile
|
|||||||
* For external gradle modules, fake npm packages will be created and added to `package.json`
|
* For external gradle modules, fake npm packages will be created and added to `package.json`
|
||||||
* as path to directory.
|
* as path to directory.
|
||||||
*/
|
*/
|
||||||
internal class NpmResolver private constructor(val rootProject: Project) {
|
internal class NpmResolver private constructor(val rootProject: Project) : AutoCloseable {
|
||||||
companion object {
|
companion object {
|
||||||
fun resolve(project: Project): ResolutionCallResult {
|
fun resolve(project: Project): ResolutionCallResult {
|
||||||
val rootProject = project.rootProject
|
val rootProject = project.rootProject
|
||||||
@@ -47,7 +47,9 @@ internal class NpmResolver private constructor(val rootProject: Project) {
|
|||||||
|
|
||||||
return if (resolved != null) AlreadyResolved(ProjectData[project]!!.resolved!!)
|
return if (resolved != null) AlreadyResolved(ProjectData[project]!!.resolved!!)
|
||||||
else {
|
else {
|
||||||
NpmResolver(rootProject).resolve(rootProject, null)!!
|
val resolver = NpmResolver(rootProject)
|
||||||
|
resolver.resolve(rootProject)!!
|
||||||
|
resolver.close()
|
||||||
ResolvedNow(ProjectData[project]!!.resolved!!)
|
ResolvedNow(ProjectData[project]!!.resolved!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,8 +79,8 @@ internal class NpmResolver private constructor(val rootProject: Project) {
|
|||||||
|
|
||||||
private val nodeJs = NodeJsPlugin.apply(rootProject).root
|
private val nodeJs = NodeJsPlugin.apply(rootProject).root
|
||||||
private val npmProject = rootProject.npmProject
|
private val npmProject = rootProject.npmProject
|
||||||
|
private val gradleNodeModules = GradleNodeModulesCache(rootProject)
|
||||||
private val packageManager = nodeJs.packageManager
|
private val packageManager = nodeJs.packageManager
|
||||||
private val hoistGradleNodeModules = npmProject.hoistGradleNodeModules
|
|
||||||
private val npmPackages = mutableListOf<NpmPackage>()
|
private val npmPackages = mutableListOf<NpmPackage>()
|
||||||
private val requiredByTasks = mutableMapOf<RequiresNpmDependencies, Collection<RequiredKotlinJsDependency>>()
|
private val requiredByTasks = mutableMapOf<RequiresNpmDependencies, Collection<RequiredKotlinJsDependency>>()
|
||||||
private val gson = GsonBuilder()
|
private val gson = GsonBuilder()
|
||||||
@@ -120,27 +122,20 @@ internal class NpmResolver private constructor(val rootProject: Project) {
|
|||||||
packageManagerInstalled = true
|
packageManagerInstalled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getOrResolve(project: Project, parentGradleModules: GradleNodeModulesBuilder?): ResolvedProject {
|
private fun getOrResolve(project: Project): ResolvedProject {
|
||||||
return (ProjectData[project] ?: resolve(project, parentGradleModules)!!).resolved!!
|
return (ProjectData[project] ?: resolve(project)!!).resolved!!
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolve(
|
private fun resolve(project: Project): ProjectData? {
|
||||||
project: Project,
|
|
||||||
parentGradleModules: GradleNodeModulesBuilder?
|
|
||||||
): ProjectData? {
|
|
||||||
val result = ProjectData().also {
|
val result = ProjectData().also {
|
||||||
ProjectData[project] = it
|
ProjectData[project] = it
|
||||||
}
|
}
|
||||||
|
|
||||||
val gradleModules =
|
|
||||||
if (hoistGradleNodeModules && parentGradleModules != null) parentGradleModules
|
|
||||||
else GradleNodeModulesBuilder(project)
|
|
||||||
|
|
||||||
project.subprojects.forEach {
|
project.subprojects.forEach {
|
||||||
getOrResolve(it, gradleModules)
|
getOrResolve(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
val npmPackage = extractNpmPackage(project, gradleModules, parentGradleModules)
|
val npmPackage = extractNpmPackage(project)
|
||||||
if (npmPackage != null) {
|
if (npmPackage != null) {
|
||||||
npmPackage.savePackageJson(gson)
|
npmPackage.savePackageJson(gson)
|
||||||
|
|
||||||
@@ -159,35 +154,27 @@ internal class NpmResolver private constructor(val rootProject: Project) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gradleModules != parentGradleModules) {
|
|
||||||
gradleModules.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun extractNpmPackage(
|
private fun extractNpmPackage(project: Project): NpmPackage? {
|
||||||
project: Project,
|
|
||||||
gradleComponents: GradleNodeModulesBuilder,
|
|
||||||
parentGradleModules: GradleNodeModulesBuilder?
|
|
||||||
): NpmPackage? {
|
|
||||||
val packageJson = PackageJson(project.name, project.version.toString())
|
val packageJson = PackageJson(project.name, project.version.toString())
|
||||||
val npmDependencies = mutableSetOf<NpmDependency>()
|
val npmDependencies = mutableSetOf<NpmDependency>()
|
||||||
|
val gradleDeps = NpmProjectGradleDeps()
|
||||||
|
|
||||||
visitTasksRequiredDependencies(project, npmDependencies, gradleComponents)
|
visitTasksRequiredDependencies(project, npmDependencies, gradleDeps)
|
||||||
|
|
||||||
visitNpmDependencies(project, npmDependencies, gradleComponents, packageJson)
|
collectDependencies(project, npmDependencies, gradleDeps, packageJson)
|
||||||
|
|
||||||
if (!hoistGradleNodeModules || project == project.rootProject) {
|
gradleDeps.externalModules.forEach {
|
||||||
gradleComponents.modules.forEach {
|
val relativePath = it.path.relativeTo(NpmProject[project].nodeWorkDir)
|
||||||
val relativePath = it.path.relativeTo(NpmProject[project].nodeWorkDir)
|
packageJson.dependencies[it.name] = "file:$relativePath"
|
||||||
packageJson.dependencies[it.name] = "file:$relativePath"
|
}
|
||||||
}
|
|
||||||
gradleComponents.projects.forEach {
|
gradleDeps.internalModules.forEach {
|
||||||
val npmPackage = getOrResolve(it, parentGradleModules).npmPackage
|
val npmPackage = getOrResolve(it).npmPackage
|
||||||
if (npmPackage != null) {
|
if (npmPackage != null) {
|
||||||
packageJson.dependencies[npmPackage.packageJson.name] = npmPackage.packageJson.version
|
packageJson.dependencies[npmPackage.packageJson.name] = npmPackage.packageJson.version
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,7 +193,7 @@ internal class NpmResolver private constructor(val rootProject: Project) {
|
|||||||
private fun visitTasksRequiredDependencies(
|
private fun visitTasksRequiredDependencies(
|
||||||
project: Project,
|
project: Project,
|
||||||
npmDependencies: MutableSet<NpmDependency>,
|
npmDependencies: MutableSet<NpmDependency>,
|
||||||
gradleComponents: GradleNodeModulesBuilder
|
gradleDeps: NpmProjectGradleDeps
|
||||||
) {
|
) {
|
||||||
val requiredDependencies = mutableListOf<Dependency>()
|
val requiredDependencies = mutableListOf<Dependency>()
|
||||||
|
|
||||||
@@ -227,23 +214,23 @@ internal class NpmResolver private constructor(val rootProject: Project) {
|
|||||||
configuration.dependencies.add(it)
|
configuration.dependencies.add(it)
|
||||||
}
|
}
|
||||||
configuration.resolve()
|
configuration.resolve()
|
||||||
visitConfiguration(configuration, npmDependencies, gradleComponents)
|
visitConfiguration(configuration, npmDependencies, gradleDeps)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun visitNpmDependencies(
|
private fun collectDependencies(
|
||||||
project: Project,
|
project: Project,
|
||||||
npmDependencies: MutableSet<NpmDependency>,
|
npmDependencies: MutableSet<NpmDependency>,
|
||||||
gradleComponents: GradleNodeModulesBuilder,
|
gradleDeps: NpmProjectGradleDeps,
|
||||||
packageJson: PackageJson
|
packageJson: PackageJson
|
||||||
) {
|
) {
|
||||||
val kotlin = project.kotlinExtensionOrNull
|
val kotlin = project.kotlinExtensionOrNull
|
||||||
|
|
||||||
if (kotlin != null) {
|
if (kotlin != null) {
|
||||||
when (kotlin) {
|
when (kotlin) {
|
||||||
is KotlinSingleTargetExtension -> visitTarget(kotlin.target, project, npmDependencies, gradleComponents, packageJson)
|
is KotlinSingleTargetExtension -> visitTarget(kotlin.target, project, npmDependencies, gradleDeps, packageJson)
|
||||||
is KotlinMultiplatformExtension -> kotlin.targets.forEach {
|
is KotlinMultiplatformExtension -> kotlin.targets.forEach {
|
||||||
visitTarget(it, project, npmDependencies, gradleComponents, packageJson)
|
visitTarget(it, project, npmDependencies, gradleDeps, packageJson)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,14 +247,14 @@ internal class NpmResolver private constructor(val rootProject: Project) {
|
|||||||
target: KotlinTarget,
|
target: KotlinTarget,
|
||||||
project: Project,
|
project: Project,
|
||||||
npmDependencies: MutableSet<NpmDependency>,
|
npmDependencies: MutableSet<NpmDependency>,
|
||||||
gradleComponents: GradleNodeModulesBuilder,
|
gradleDeps: NpmProjectGradleDeps,
|
||||||
packageJson: PackageJson
|
packageJson: PackageJson
|
||||||
) {
|
) {
|
||||||
if (target.platformType == KotlinPlatformType.js) {
|
if (target.platformType == KotlinPlatformType.js) {
|
||||||
target.compilations.toList().forEach { compilation ->
|
target.compilations.toList().forEach { compilation ->
|
||||||
compilation.relatedConfigurationNames.forEach {
|
compilation.relatedConfigurationNames.forEach {
|
||||||
val configuration = project.configurations.getByName(it)
|
val configuration = project.configurations.getByName(it)
|
||||||
visitConfiguration(configuration, npmDependencies, gradleComponents)
|
visitConfiguration(configuration, npmDependencies, gradleDeps)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compilation is KotlinJsCompilation) {
|
if (compilation is KotlinJsCompilation) {
|
||||||
@@ -284,9 +271,9 @@ internal class NpmResolver private constructor(val rootProject: Project) {
|
|||||||
private fun visitConfiguration(
|
private fun visitConfiguration(
|
||||||
configuration: Configuration,
|
configuration: Configuration,
|
||||||
npmDependencies: MutableSet<NpmDependency>,
|
npmDependencies: MutableSet<NpmDependency>,
|
||||||
gradleComponents: GradleNodeModulesBuilder
|
gradleDeps: NpmProjectGradleDeps
|
||||||
) {
|
) {
|
||||||
gradleComponents.visitConfiguration(configuration)
|
gradleNodeModules.collectDependenciesFromConfiguration(configuration, gradleDeps)
|
||||||
|
|
||||||
configuration.allDependencies.forEach { dependency ->
|
configuration.allDependencies.forEach { dependency ->
|
||||||
when (dependency) {
|
when (dependency) {
|
||||||
@@ -336,4 +323,8 @@ internal class NpmResolver private constructor(val rootProject: Project) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
gradleNodeModules.close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user