[Gradle, JS] up-to-date check on npm install, not on root package.json

#KT-34832 fixed
This commit is contained in:
Ilya Goncharov
2020-04-16 19:19:17 +03:00
parent 742e27d7f5
commit 2f8649a337
7 changed files with 35 additions and 47 deletions
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.gradle.targets.js.npm.KotlinNpmResolutionManager
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmApi import org.jetbrains.kotlin.gradle.targets.js.npm.NpmApi
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.RootPackageJsonTask
import org.jetbrains.kotlin.gradle.targets.js.yarn.Yarn import org.jetbrains.kotlin.gradle.targets.js.yarn.Yarn
import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore
import java.io.File import java.io.File
@@ -56,6 +57,9 @@ open class NodeJsRootExtension(val rootProject: Project) : ConfigurationPhaseAwa
val npmInstallTask: KotlinNpmInstallTask val npmInstallTask: KotlinNpmInstallTask
get() = rootProject.tasks.getByName(KotlinNpmInstallTask.NAME) as KotlinNpmInstallTask get() = rootProject.tasks.getByName(KotlinNpmInstallTask.NAME) as KotlinNpmInstallTask
val rootPackageJsonTask: RootPackageJsonTask
get() = rootProject.tasks.getByName(RootPackageJsonTask.NAME) as RootPackageJsonTask
val rootPackageDir: File val rootPackageDir: File
get() = rootProject.buildDir.resolve("js") get() = rootProject.buildDir.resolve("js")
@@ -117,18 +117,33 @@ class KotlinNpmResolutionManager(private val nodeJsSettings: NodeJsRootExtension
return (state as ResolutionState.Installed).resolved return (state as ResolutionState.Installed).resolved
} }
val installUpToDate = nodeJsSettings.npmInstallTask.state.upToDate
val forceUpToDate = installUpToDate && !forceFullResolve
val npmResolution = prepareIfNeeded(requireUpToDateReason = reason) val npmResolution = prepareIfNeeded(requireUpToDateReason = reason)
val npmResolutions = npmResolution val npmResolutions = npmResolution
.projects .projects
.values .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.packageManager.resolveRootProject(
nodeJsSettings.rootProject, nodeJsSettings.rootProject,
npmResolutions.flatMap { it.npmProjects }, npmResolutions,
false, upToDate,
args args
) )
upToDateChecks.forEach { it.commit() }
return ResolutionState.Installed((state as ResolutionState.Prepared).resolved) return ResolutionState.Installed((state as ResolutionState.Prepared).resolved)
.apply { .apply {
state = this state = this
@@ -166,13 +181,12 @@ class KotlinNpmResolutionManager(private val nodeJsSettings: NodeJsRootExtension
when (state1) { when (state1) {
is ResolutionState.Prepared -> alreadyResolved(state1.resolved) is ResolutionState.Prepared -> alreadyResolved(state1.resolved)
is ResolutionState.Configuring -> { is ResolutionState.Configuring -> {
val upToDate = nodeJsSettings.npmInstallTask.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")
} }
val forceUpToDate = upToDate && !forceFullResolve state1.resolver.close().also {
state1.resolver.close(forceUpToDate).also {
this.state = ResolutionState.Prepared(it) this.state = ResolutionState.Prepared(it)
state1.resolver.closePlugins(it) state1.resolver.closePlugins(it)
} }
@@ -19,9 +19,7 @@ interface NpmApi {
fun prepareRootProject( fun prepareRootProject(
rootProject: Project, rootProject: Project,
subProjects: Collection<KotlinCompilationNpmResolution>, subProjects: Collection<KotlinCompilationNpmResolution>
skipExecution: Boolean,
cliArgs: List<String>
) )
fun resolveRootProject( fun resolveRootProject(
@@ -15,7 +15,6 @@ 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.KotlinRootNpmResolution import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinRootNpmResolution
@@ -88,7 +87,7 @@ internal class KotlinRootNpmResolver internal constructor(
/** /**
* Don't use directly, use [KotlinNpmResolutionManager.installIfNeeded] instead. * Don't use directly, use [KotlinNpmResolutionManager.installIfNeeded] instead.
*/ */
internal fun close(forceUpToDate: Boolean): KotlinRootNpmResolution { internal fun close(): KotlinRootNpmResolution {
check(!closed) check(!closed)
closed = true closed = true
@@ -99,24 +98,11 @@ internal class KotlinRootNpmResolver internal constructor(
gradleNodeModules.close() gradleNodeModules.close()
// 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.prepareRootProject( nodeJs.packageManager.prepareRootProject(
rootProject, rootProject,
allNpmPackages, allNpmPackages
upToDate,
nodeJs.npmInstallTask.args
) )
upToDateChecks.forEach { it.commit() }
return KotlinRootNpmResolution( return KotlinRootNpmResolution(
rootProject, rootProject,
projectResolutions, projectResolutions,
@@ -47,14 +47,10 @@ class Yarn : NpmApi {
override fun prepareRootProject( override fun prepareRootProject(
rootProject: Project, rootProject: Project,
subProjects: Collection<KotlinCompilationNpmResolution>, subProjects: Collection<KotlinCompilationNpmResolution>
skipExecution: Boolean,
cliArgs: List<String>
) = getDelegate(rootProject.project) ) = getDelegate(rootProject.project)
.prepareRootProject( .prepareRootProject(
rootProject, rootProject,
subProjects, subProjects
skipExecution,
cliArgs
) )
} }
@@ -32,14 +32,10 @@ class YarnSimple : YarnBasics() {
npmProjects: Collection<KotlinCompilationNpmResolution>, npmProjects: Collection<KotlinCompilationNpmResolution>,
skipExecution: Boolean, skipExecution: Boolean,
cliArgs: List<String> cliArgs: List<String>
) { ) = Unit
TODO("Not yet implemented")
}
override fun prepareRootProject( override fun prepareRootProject(
rootProject: Project, rootProject: Project,
subProjects: Collection<KotlinCompilationNpmResolution>, subProjects: Collection<KotlinCompilationNpmResolution>
skipExecution: Boolean,
cliArgs: List<String>
) = Unit ) = Unit
} }
@@ -17,30 +17,24 @@ class YarnWorkspaces : YarnBasics() {
override fun prepareRootProject( override fun prepareRootProject(
rootProject: Project, rootProject: Project,
subProjects: Collection<KotlinCompilationNpmResolution>, subProjects: Collection<KotlinCompilationNpmResolution>
skipExecution: Boolean,
cliArgs: List<String>
) { ) {
check(rootProject == rootProject.rootProject) check(rootProject == rootProject.rootProject)
if (!skipExecution) setup(rootProject) setup(rootProject)
return prepareRootPackageJson( return prepareRootPackageJson(
rootProject, rootProject,
subProjects, subProjects
skipExecution
) )
} }
private fun prepareRootPackageJson( private fun prepareRootPackageJson(
rootProject: Project, rootProject: Project,
npmProjects: Collection<KotlinCompilationNpmResolution>, npmProjects: Collection<KotlinCompilationNpmResolution>
skipExecution: Boolean
) { ) {
val nodeJs = NodeJsRootPlugin.apply(rootProject) val nodeJs = NodeJsRootPlugin.apply(rootProject)
val rootPackageJsonFile = nodeJs.rootPackageJson val rootPackageJsonFile = nodeJs.rootPackageJson
if (!skipExecution) { saveRootProjectWorkspacesPackageJson(rootProject, npmProjects, rootPackageJsonFile)
saveRootProjectWorkspacesPackageJson(rootProject, npmProjects, rootPackageJsonFile)
}
} }
override fun resolveRootProject( override fun resolveRootProject(