diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/ProcessedFilesCache.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/ProcessedFilesCache.kt index 4514d08c210..fc263f5fa36 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/ProcessedFilesCache.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/ProcessedFilesCache.kt @@ -9,9 +9,8 @@ import com.google.gson.GsonBuilder import com.google.gson.stream.JsonReader import com.google.gson.stream.JsonToken import com.google.gson.stream.JsonWriter -import org.gradle.api.logging.Logger +import org.gradle.internal.hash.FileHasher import java.io.File -import java.security.MessageDigest /** * Cache for preventing processing some files twice. @@ -24,6 +23,7 @@ import java.security.MessageDigest * @param version When updating logic in `compute`, `version` should be increased to invalidate cache */ internal open class ProcessedFilesCache( + val fileHasher: FileHasher, val projectDir: File, val targetDir: File, stateFileName: String, @@ -192,19 +192,7 @@ internal open class ProcessedFilesCache( file: File, compute: () -> File? ): String? { - val md = MessageDigest.getInstance("MD5") - val buffer = ByteArray(4048) - file.inputStream().use { input -> - while (true) { - val len = input.read(buffer) - if (len < 0) { - break - } - md.update(buffer, 0, len) - } - } - - val hash = md.digest() + val hash = fileHasher.hash(file).toByteArray() val old = state[hash] if (old != null) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension.kt index 14393c3a0c3..338fc80674f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension.kt @@ -16,6 +16,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.resolver.PACKAGE_JSON_UMBRELLA_TASK_NAME import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask +import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmCachesSetup import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.RootPackageJsonTask import org.jetbrains.kotlin.gradle.targets.js.yarn.Yarn import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore @@ -66,6 +67,9 @@ open class NodeJsRootExtension(@Transient val rootProject: Project) : Configurat val rootPackageJsonTaskProvider: TaskProvider? get() = rootProject?.tasks?.withType(RootPackageJsonTask::class.java)?.named(RootPackageJsonTask.NAME) + val npmCachesSetupTaskProvider: TaskProvider? + get() = rootProject?.tasks?.withType(KotlinNpmCachesSetup::class.java)?.named(KotlinNpmCachesSetup.NAME) + val rootPackageDir: File by lazy { rootProject.buildDir.resolve("js") } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootPlugin.kt index d073d87681b..01d1cd8ea7b 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootPlugin.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.gradle.targets.js.MultiplePluginDeclarationDetector import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension.Companion.EXTENSION_NAME import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.PACKAGE_JSON_UMBRELLA_TASK_NAME import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask +import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmCachesSetup import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin import org.jetbrains.kotlin.gradle.tasks.CleanDataTask import org.jetbrains.kotlin.gradle.tasks.registerTask @@ -48,6 +49,11 @@ open class NodeJsRootPlugin : Plugin { it.mustRunAfter(rootClean) } + registerTask(KotlinNpmCachesSetup.NAME) { + it.group = TASKS_GROUP_NAME + it.description = "Setup file hasher for caches" + } + registerTask(PACKAGE_JSON_UMBRELLA_TASK_NAME) YarnPlugin.apply(project) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/AbstractNodeModulesCache.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/AbstractNodeModulesCache.kt index 83ee6c7201f..6561ec37e29 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/AbstractNodeModulesCache.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/AbstractNodeModulesCache.kt @@ -7,9 +7,9 @@ package org.jetbrains.kotlin.gradle.targets.js.npm import com.google.gson.GsonBuilder import org.gradle.api.file.DirectoryProperty -import org.gradle.api.invocation.Gradle import org.gradle.api.services.BuildService import org.gradle.api.services.BuildServiceParameters +import org.gradle.internal.hash.FileHasher import org.jetbrains.kotlin.gradle.internal.ProcessedFilesCache import java.io.File @@ -26,12 +26,17 @@ internal abstract class AbstractNodeModulesCache : AutoCloseable, BuildService = + internal val gradleNodeModulesProvider: Provider = rootProject.gradle.sharedServices.registerIfAbsent("gradle-node-modules", GradleNodeModulesCache::class.java) { it.parameters.cacheDir.set(nodeJs.nodeModulesGradleCacheDir) it.parameters.rootProjectDir.set(rootProject.projectDir) @@ -81,7 +80,7 @@ internal class KotlinRootNpmResolver internal constructor( it.fs = fs } - private val compositeNodeModulesProvider: Provider = + internal val compositeNodeModulesProvider: Provider = rootProject.gradle.sharedServices.registerIfAbsent("composite-node-modules", CompositeNodeModulesCache::class.java) { it.parameters.cacheDir.set(nodeJs.nodeModulesGradleCacheDir) it.parameters.rootProjectDir.set(rootProject.projectDir) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/tasks/KotlinNpmCachesSetup.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/tasks/KotlinNpmCachesSetup.kt new file mode 100644 index 00000000000..30b29e02c7f --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/tasks/KotlinNpmCachesSetup.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2021 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.tasks + +import org.gradle.api.DefaultTask +import org.gradle.api.tasks.TaskAction +import org.gradle.internal.hash.FileHasher +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin +import javax.inject.Inject + +abstract class KotlinNpmCachesSetup : DefaultTask() { + @get:Inject + open val fileHasher: FileHasher + get() = throw UnsupportedOperationException() + + @Transient + private val nodeJs = NodeJsRootPlugin.apply(project.rootProject) + private val gradleNodeModules = nodeJs.npmResolutionManager.resolver.gradleNodeModulesProvider + private val compositeNodeModules = nodeJs.npmResolutionManager.resolver.compositeNodeModulesProvider + + @TaskAction + fun setup() { + gradleNodeModules.get().fileHasher = fileHasher + compositeNodeModules.get().fileHasher = fileHasher + } + + companion object { + const val NAME = "kotlinNpmCachesSetup" + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/tasks/KotlinPackageJsonTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/tasks/KotlinPackageJsonTask.kt index f23cf941819..c67ee0474bb 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/tasks/KotlinPackageJsonTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/tasks/KotlinPackageJsonTask.kt @@ -96,6 +96,7 @@ open class KotlinPackageJsonTask : DefaultTask() { val rootClean = project.rootProject.tasks.named(BasePlugin.CLEAN_TASK_NAME) val npmInstallTask = nodeJs.npmInstallTaskProvider + val npmCachesSetupTask = nodeJs.npmCachesSetupTaskProvider val packageJsonTaskName = npmProject.packageJsonTaskName val packageJsonUmbrella = nodeJs.packageJsonUmbrellaTaskProvider val packageJsonTask = project.registerTask(packageJsonTaskName) { task -> @@ -105,6 +106,7 @@ open class KotlinPackageJsonTask : DefaultTask() { task.group = NodeJsRootPlugin.TASKS_GROUP_NAME task.dependsOn(target.project.provider { task.findDependentTasks() }) + task.dependsOn(npmCachesSetupTask) task.mustRunAfter(rootClean) } packageJsonUmbrella.configure { task ->