[Gradle, JS] Replace close on prepare
#KT-34832 fixed
This commit is contained in:
+1
-5
@@ -19,7 +19,7 @@ internal class DukatRootResolverPlugin(val resolver: KotlinRootNpmResolver) : Ro
|
|||||||
return listOf(plugin)
|
return listOf(plugin)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun resolve(resolution: KotlinRootNpmResolution) {
|
override fun close(resolution: KotlinRootNpmResolution) {
|
||||||
if (resolver.forceFullResolve) {
|
if (resolver.forceFullResolve) {
|
||||||
// inside idea import
|
// inside idea import
|
||||||
compilations.forEach {
|
compilations.forEach {
|
||||||
@@ -27,8 +27,4 @@ internal class DukatRootResolverPlugin(val resolver: KotlinRootNpmResolver) : Ro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun close(resolution: KotlinRootNpmResolution) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+48
-54
@@ -93,12 +93,25 @@ class KotlinNpmResolutionManager(private val nodeJsSettings: NodeJsRootExtension
|
|||||||
get() = resolver.compilations.map { it.npmProject }
|
get() = resolver.compilations.map { it.npmProject }
|
||||||
}
|
}
|
||||||
|
|
||||||
open class Prepared(val resolved: KotlinRootNpmResolution) : ResolutionState() {
|
open class Prepared(val preparedInstallation: KotlinRootNpmResolver.Installation) : ResolutionState() {
|
||||||
override val npmProjects: List<NpmProject>
|
override val npmProjects: List<NpmProject>
|
||||||
get() = resolved.projects.values.flatMap { it.npmProjects.map { it.npmProject } }
|
get() = npmProjectsByProjectResolutions(preparedInstallation.projectResolutions)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Installed(resolved: KotlinRootNpmResolution) : Prepared(resolved)
|
class Installed(val resolved: KotlinRootNpmResolution) : ResolutionState() {
|
||||||
|
override val npmProjects: List<NpmProject>
|
||||||
|
get() = npmProjectsByProjectResolutions(resolved.projects)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun npmProjectsByProjectResolutions(
|
||||||
|
resolutions: Map<Project, KotlinProjectNpmResolution>
|
||||||
|
): List<NpmProject> {
|
||||||
|
return resolutions
|
||||||
|
.values
|
||||||
|
.flatMap { it.npmProjects.map { it.npmProject } }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Incubating
|
@Incubating
|
||||||
@@ -107,49 +120,29 @@ class KotlinNpmResolutionManager(private val nodeJsSettings: NodeJsRootExtension
|
|||||||
internal fun requireConfiguringState(): KotlinRootNpmResolver =
|
internal fun requireConfiguringState(): KotlinRootNpmResolver =
|
||||||
(this.state as? ResolutionState.Configuring ?: error("NPM Dependencies already resolved and installed")).resolver
|
(this.state as? ResolutionState.Configuring ?: error("NPM Dependencies already resolved and installed")).resolver
|
||||||
|
|
||||||
internal fun prepare() = prepareIfNeeded(requireNotInstalled = true)
|
internal fun prepare() = prepareIfNeeded(requireNotPrepared = true)
|
||||||
|
|
||||||
internal fun installIfNeeded(
|
internal fun installIfNeeded(
|
||||||
reason: String = "",
|
reason: String? = "",
|
||||||
args: List<String> = emptyList()
|
args: List<String> = emptyList()
|
||||||
): KotlinRootNpmResolution {
|
): KotlinRootNpmResolution {
|
||||||
if (state is ResolutionState.Installed) {
|
synchronized(this) {
|
||||||
return (state as ResolutionState.Installed).resolved
|
if (state is ResolutionState.Installed) {
|
||||||
|
return (state as ResolutionState.Installed).resolved
|
||||||
|
}
|
||||||
|
|
||||||
|
val installUpToDate = nodeJsSettings.npmInstallTask.state.upToDate
|
||||||
|
val forceUpToDate = installUpToDate && !forceFullResolve
|
||||||
|
|
||||||
|
val installation = prepareIfNeeded(requireUpToDateReason = reason)
|
||||||
|
val resolution = installation
|
||||||
|
.install(forceUpToDate, args)
|
||||||
|
state = ResolutionState.Installed(resolution)
|
||||||
|
|
||||||
|
installation.closePlugins(resolution)
|
||||||
|
|
||||||
|
return resolution
|
||||||
}
|
}
|
||||||
|
|
||||||
val installUpToDate = nodeJsSettings.npmInstallTask.state.upToDate
|
|
||||||
val forceUpToDate = installUpToDate && !forceFullResolve
|
|
||||||
|
|
||||||
val npmResolution = prepareIfNeeded(requireUpToDateReason = reason)
|
|
||||||
val npmResolutions = npmResolution
|
|
||||||
.projects
|
|
||||||
.values
|
|
||||||
.flatMap { it.npmProjects }
|
|
||||||
|
|
||||||
// we need manual up-to-date checking to avoid call package manager during
|
|
||||||
// idea import if nothing was changed
|
|
||||||
// we should call it even kotlinNpmInstall task is up-to-date (skipPackageManager is true)
|
|
||||||
// because our upToDateChecks saves state for next execution
|
|
||||||
val upToDateChecks = npmResolutions.map {
|
|
||||||
PackageJsonUpToDateCheck(it.npmProject)
|
|
||||||
}
|
|
||||||
val upToDate = forceUpToDate || upToDateChecks.all { it.upToDate }
|
|
||||||
|
|
||||||
nodeJsSettings.packageManager.resolveRootProject(
|
|
||||||
nodeJsSettings.rootProject,
|
|
||||||
npmResolutions,
|
|
||||||
upToDate,
|
|
||||||
args
|
|
||||||
)
|
|
||||||
|
|
||||||
upToDateChecks.forEach { it.commit() }
|
|
||||||
|
|
||||||
return ResolutionState.Installed((state as ResolutionState.Prepared).resolved)
|
|
||||||
.apply {
|
|
||||||
state = this
|
|
||||||
npmResolution.plugins
|
|
||||||
.forEach { it.resolve(npmResolution) }
|
|
||||||
}.resolved
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun requireAlreadyInstalled(project: Project, reason: String = ""): KotlinProjectNpmResolution =
|
internal fun requireAlreadyInstalled(project: Project, reason: String = ""): KotlinProjectNpmResolution =
|
||||||
@@ -161,39 +154,40 @@ class KotlinNpmResolutionManager(private val nodeJsSettings: NodeJsRootExtension
|
|||||||
/**
|
/**
|
||||||
* @param requireUpToDateReason Check that project already resolved,
|
* @param requireUpToDateReason Check that project already resolved,
|
||||||
* or it is up-to-date but just not closed. Show given message if it is not.
|
* or it is up-to-date but just not closed. Show given message if it is not.
|
||||||
* @param requireNotInstalled Check that project is not resolved
|
* @param requireNotPrepared Check that project is not prepared
|
||||||
*/
|
*/
|
||||||
private fun prepareIfNeeded(
|
private fun prepareIfNeeded(
|
||||||
requireUpToDateReason: String? = null,
|
requireUpToDateReason: String? = null,
|
||||||
requireNotInstalled: Boolean = false
|
requireNotPrepared: Boolean = false
|
||||||
): KotlinRootNpmResolution {
|
): KotlinRootNpmResolver.Installation {
|
||||||
fun alreadyResolved(resolution: KotlinRootNpmResolution): KotlinRootNpmResolution {
|
fun alreadyResolved(installation: KotlinRootNpmResolver.Installation): KotlinRootNpmResolver.Installation {
|
||||||
if (requireNotInstalled) error("Project already resolved")
|
if (requireNotPrepared) error("Project already prepared")
|
||||||
return resolution
|
return installation
|
||||||
}
|
}
|
||||||
|
|
||||||
val state0 = this.state
|
val state0 = this.state
|
||||||
return when (state0) {
|
return when (state0) {
|
||||||
is ResolutionState.Prepared -> alreadyResolved(state0.resolved)
|
is ResolutionState.Prepared -> alreadyResolved(state0.preparedInstallation)
|
||||||
is ResolutionState.Configuring -> {
|
is ResolutionState.Configuring -> {
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
val state1 = this.state
|
val state1 = this.state
|
||||||
when (state1) {
|
when (state1) {
|
||||||
is ResolutionState.Prepared -> alreadyResolved(state1.resolved)
|
is ResolutionState.Prepared -> alreadyResolved(state1.preparedInstallation)
|
||||||
is ResolutionState.Configuring -> {
|
is ResolutionState.Configuring -> {
|
||||||
val upToDate = nodeJsSettings.rootPackageJsonTask.state.upToDate
|
val upToDate = nodeJsSettings.rootPackageJsonTask.state.upToDate
|
||||||
if (requireUpToDateReason != null && !upToDate) {
|
if (requireUpToDateReason != null && !upToDate) {
|
||||||
error("NPM dependencies should be resolved $requireUpToDateReason")
|
error("NPM dependencies should be resolved $requireUpToDateReason")
|
||||||
}
|
}
|
||||||
|
|
||||||
state1.resolver.close().also {
|
state1.resolver.prepareInstallation().also {
|
||||||
this.state = ResolutionState.Prepared(it)
|
this.state = ResolutionState.Prepared(it)
|
||||||
state1.resolver.closePlugins(it)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
is ResolutionState.Installed -> error("Project already installed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
is ResolutionState.Installed -> error("Project already installed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,19 +196,19 @@ class KotlinNpmResolutionManager(private val nodeJsSettings: NodeJsRootExtension
|
|||||||
|
|
||||||
val resolvedProject =
|
val resolvedProject =
|
||||||
if (forceFullResolve) {
|
if (forceFullResolve) {
|
||||||
prepareIfNeeded()
|
installIfNeeded(reason = null)[project]
|
||||||
installIfNeeded()[project]
|
|
||||||
} else {
|
} else {
|
||||||
// may return null only during npm resolution
|
// may return null only during npm resolution
|
||||||
// (it can be called since NpmDependency added to configuration that
|
// (it can be called since NpmDependency added to configuration that
|
||||||
// requires resolve to build package.json, in this case we should just skip this call)
|
// requires resolve to build package.json, in this case we should just skip this call)
|
||||||
val state0 = state
|
val state0 = state
|
||||||
when (state0) {
|
when (state0) {
|
||||||
is ResolutionState.Prepared -> state0.resolved[project]
|
is ResolutionState.Prepared -> state0.preparedInstallation[project]
|
||||||
is ResolutionState.Configuring -> {
|
is ResolutionState.Configuring -> {
|
||||||
return null
|
return null
|
||||||
//error("Cannot use NpmDependency before :kotlinNpmInstall task execution")
|
//error("Cannot use NpmDependency before :kotlinNpmInstall task execution")
|
||||||
}
|
}
|
||||||
|
is ResolutionState.Installed -> state0.resolved[project]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-1
@@ -10,6 +10,5 @@ import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinCompilationNpmR
|
|||||||
|
|
||||||
internal interface RootResolverPlugin {
|
internal interface RootResolverPlugin {
|
||||||
fun createCompilationResolverPlugins(resolver: KotlinCompilationNpmResolver): List<CompilationResolverPlugin>
|
fun createCompilationResolverPlugins(resolver: KotlinCompilationNpmResolver): List<CompilationResolverPlugin>
|
||||||
fun resolve(resolution: KotlinRootNpmResolution)
|
|
||||||
fun close(resolution: KotlinRootNpmResolution)
|
fun close(resolution: KotlinRootNpmResolution)
|
||||||
}
|
}
|
||||||
+1
-3
@@ -6,12 +6,10 @@
|
|||||||
package org.jetbrains.kotlin.gradle.targets.js.npm.resolved
|
package org.jetbrains.kotlin.gradle.targets.js.npm.resolved
|
||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.plugins.RootResolverPlugin
|
|
||||||
|
|
||||||
internal class KotlinRootNpmResolution(
|
internal class KotlinRootNpmResolution(
|
||||||
val rootProject: Project,
|
val rootProject: Project,
|
||||||
val projects: Map<Project, KotlinProjectNpmResolution>,
|
internal val projects: Map<Project, KotlinProjectNpmResolution>
|
||||||
val plugins: List<RootResolverPlugin>
|
|
||||||
) {
|
) {
|
||||||
operator fun get(project: Project) = projects[project] ?: KotlinProjectNpmResolution.empty(project)
|
operator fun get(project: Project) = projects[project] ?: KotlinProjectNpmResolution.empty(project)
|
||||||
}
|
}
|
||||||
+74
-22
@@ -15,8 +15,10 @@ import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
|
|||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.CompositeNodeModulesCache
|
import org.jetbrains.kotlin.gradle.targets.js.npm.CompositeNodeModulesCache
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.GradleNodeModulesCache
|
import org.jetbrains.kotlin.gradle.targets.js.npm.GradleNodeModulesCache
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.KotlinNpmResolutionManager
|
import org.jetbrains.kotlin.gradle.targets.js.npm.KotlinNpmResolutionManager
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.PackageJsonUpToDateCheck
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.plugins.RootResolverPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.npm.plugins.RootResolverPlugin
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinCompilationNpmResolution
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinCompilationNpmResolution
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinProjectNpmResolution
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinRootNpmResolution
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinRootNpmResolution
|
||||||
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
||||||
|
|
||||||
@@ -36,7 +38,14 @@ internal class KotlinRootNpmResolver internal constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var closed: Boolean = false
|
enum class State {
|
||||||
|
CONFIGURING,
|
||||||
|
PROJECTS_CLOSED,
|
||||||
|
INSTALLED
|
||||||
|
}
|
||||||
|
|
||||||
|
@Volatile
|
||||||
|
private var state: State = State.CONFIGURING
|
||||||
|
|
||||||
val gradleNodeModules = GradleNodeModulesCache(nodeJs)
|
val gradleNodeModules = GradleNodeModulesCache(nodeJs)
|
||||||
val compositeNodeModules = CompositeNodeModulesCache(nodeJs)
|
val compositeNodeModules = CompositeNodeModulesCache(nodeJs)
|
||||||
@@ -47,7 +56,7 @@ internal class KotlinRootNpmResolver internal constructor(
|
|||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun addProject(target: Project) {
|
fun addProject(target: Project) {
|
||||||
check(!closed) { alreadyResolvedMessage("add new project: $target") }
|
check(state == State.CONFIGURING) { alreadyResolvedMessage("add new project: $target") }
|
||||||
projectResolvers[target] = KotlinProjectNpmResolver(target, this)
|
projectResolvers[target] = KotlinProjectNpmResolver(target, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,32 +96,75 @@ internal class KotlinRootNpmResolver internal constructor(
|
|||||||
/**
|
/**
|
||||||
* Don't use directly, use [KotlinNpmResolutionManager.installIfNeeded] instead.
|
* Don't use directly, use [KotlinNpmResolutionManager.installIfNeeded] instead.
|
||||||
*/
|
*/
|
||||||
internal fun close(): KotlinRootNpmResolution {
|
internal fun prepareInstallation(): Installation {
|
||||||
check(!closed)
|
synchronized(this@KotlinRootNpmResolver) {
|
||||||
closed = true
|
check(state == State.CONFIGURING) {
|
||||||
|
"Projects must be configuring"
|
||||||
|
}
|
||||||
|
state = State.PROJECTS_CLOSED
|
||||||
|
|
||||||
val projectResolutions = projectResolvers.values
|
val projectResolutions = projectResolvers.values
|
||||||
.map { it.close() }
|
.map { it.close() }
|
||||||
.associateBy { it.project }
|
.associateBy { it.project }
|
||||||
val allNpmPackages = projectResolutions.values.flatMap { it.npmProjects }
|
val allNpmPackages = projectResolutions.values.flatMap { it.npmProjects }
|
||||||
|
|
||||||
gradleNodeModules.close()
|
gradleNodeModules.close()
|
||||||
|
|
||||||
nodeJs.packageManager.prepareRootProject(
|
nodeJs.packageManager.prepareRootProject(
|
||||||
rootProject,
|
rootProject,
|
||||||
allNpmPackages
|
allNpmPackages
|
||||||
)
|
)
|
||||||
|
|
||||||
return KotlinRootNpmResolution(
|
return Installation(
|
||||||
rootProject,
|
projectResolutions
|
||||||
projectResolutions,
|
)
|
||||||
plugins
|
}
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun closePlugins(resolution: KotlinRootNpmResolution) {
|
open inner class Installation(val projectResolutions: Map<Project, KotlinProjectNpmResolution>) {
|
||||||
plugins.forEach {
|
operator fun get(project: Project) =
|
||||||
it.close(resolution)
|
projectResolutions[project] ?: KotlinProjectNpmResolution.empty(project)
|
||||||
|
|
||||||
|
internal fun install(
|
||||||
|
forceUpToDate: Boolean,
|
||||||
|
args: List<String>
|
||||||
|
): KotlinRootNpmResolution {
|
||||||
|
synchronized(this@KotlinRootNpmResolver) {
|
||||||
|
check(state == State.PROJECTS_CLOSED) {
|
||||||
|
"Projects must be closed"
|
||||||
|
}
|
||||||
|
state = State.INSTALLED
|
||||||
|
|
||||||
|
val allNpmPackages = projectResolutions
|
||||||
|
.values
|
||||||
|
.flatMap { it.npmProjects }
|
||||||
|
|
||||||
|
// we need manual up-to-date checking to avoid call package manager during
|
||||||
|
// idea import if nothing was changed
|
||||||
|
// we should call it even kotlinNpmInstall task is up-to-date (skipPackageManager is true)
|
||||||
|
// because our upToDateChecks saves state for next execution
|
||||||
|
val upToDateChecks = allNpmPackages.map {
|
||||||
|
PackageJsonUpToDateCheck(it.npmProject)
|
||||||
|
}
|
||||||
|
val upToDate = forceUpToDate || upToDateChecks.all { it.upToDate }
|
||||||
|
|
||||||
|
nodeJs.packageManager.resolveRootProject(
|
||||||
|
nodeJs.rootProject,
|
||||||
|
allNpmPackages,
|
||||||
|
upToDate,
|
||||||
|
args
|
||||||
|
)
|
||||||
|
|
||||||
|
upToDateChecks.forEach { it.commit() }
|
||||||
|
|
||||||
|
return KotlinRootNpmResolution(rootProject, projectResolutions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun closePlugins(resolution: KotlinRootNpmResolution) {
|
||||||
|
plugins.forEach {
|
||||||
|
it.close(resolution)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user