[Gradle, JS] Add npm support but default Yarn package manager left
Co-authored-by: Alexander Likhachev <Alexander.Likhachev@jetbrains.com> ^KT-64119 fixed
This commit is contained in:
committed by
Space Team
parent
f9348c69ba
commit
d18660c8f1
+21
-1
@@ -112,10 +112,30 @@ class JsIrConfigurationCacheIT : KGPBaseTest() {
|
|||||||
@DisplayName("KT-48241: configuration cache works with test dependencies")
|
@DisplayName("KT-48241: configuration cache works with test dependencies")
|
||||||
@GradleTest
|
@GradleTest
|
||||||
fun testTestDependencies(gradleVersion: GradleVersion) {
|
fun testTestDependencies(gradleVersion: GradleVersion) {
|
||||||
|
project("kotlin-js-project-with-test-dependencies", gradleVersion) {
|
||||||
|
assertSimpleConfigurationCacheScenarioWorks(
|
||||||
|
"assemble", "kotlinStorePackageLock",
|
||||||
|
buildOptions = defaultBuildOptions.copy(
|
||||||
|
jsOptions = defaultBuildOptions.jsOptions?.copy(
|
||||||
|
yarn = false
|
||||||
|
)
|
||||||
|
),
|
||||||
|
executedTaskNames = listOf(":rootPackageJson")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("KT-48241: configuration cache works with test dependencies for yarn.lock")
|
||||||
|
@GradleTest
|
||||||
|
fun testTestDependenciesYarnLock(gradleVersion: GradleVersion) {
|
||||||
project("kotlin-js-project-with-test-dependencies", gradleVersion) {
|
project("kotlin-js-project-with-test-dependencies", gradleVersion) {
|
||||||
assertSimpleConfigurationCacheScenarioWorks(
|
assertSimpleConfigurationCacheScenarioWorks(
|
||||||
"assemble", "kotlinStoreYarnLock",
|
"assemble", "kotlinStoreYarnLock",
|
||||||
buildOptions = defaultBuildOptions,
|
buildOptions = defaultBuildOptions.copy(
|
||||||
|
jsOptions = defaultBuildOptions.jsOptions?.copy(
|
||||||
|
yarn = true
|
||||||
|
)
|
||||||
|
),
|
||||||
executedTaskNames = listOf(":rootPackageJson")
|
executedTaskNames = listOf(":rootPackageJson")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-9
@@ -28,16 +28,47 @@ class JsSetupConfigurationCacheIT : KGPBaseTest() {
|
|||||||
@DisplayName("Check Node.JS setup on different platforms")
|
@DisplayName("Check Node.JS setup on different platforms")
|
||||||
@GradleTest
|
@GradleTest
|
||||||
fun checkNodeJsSetup(gradleVersion: GradleVersion) {
|
fun checkNodeJsSetup(gradleVersion: GradleVersion) {
|
||||||
project("kotlin-js-browser-project", gradleVersion) {
|
project(
|
||||||
build("kotlinUpgradeYarnLock") {
|
"kotlin-js-browser-project",
|
||||||
assertTasksExecuted(":kotlinUpgradeYarnLock")
|
gradleVersion,
|
||||||
assertConfigurationCacheStored()
|
buildOptions = defaultBuildOptions.copy(
|
||||||
}
|
jsOptions = defaultBuildOptions.jsOptions?.copy(
|
||||||
|
yarn = false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
checkNodeJsSetup("kotlinUpgradePackageLock")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
build("kotlinUpgradeYarnLock") {
|
// hack to be run on Mac m*
|
||||||
assertTasksUpToDate(":kotlinUpgradeYarnLock")
|
@DisplayName("Check Node.JS setup on different platforms with Yarn")
|
||||||
assertConfigurationCacheReused()
|
@GradleTest
|
||||||
}
|
fun checkNodeJsSetupYarn(gradleVersion: GradleVersion) {
|
||||||
|
project(
|
||||||
|
"kotlin-js-browser-project",
|
||||||
|
gradleVersion,
|
||||||
|
buildOptions = defaultBuildOptions.copy(
|
||||||
|
jsOptions = defaultBuildOptions.jsOptions?.copy(
|
||||||
|
yarn = true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
checkNodeJsSetup("kotlinUpgradeYarnLock")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun TestProject.checkNodeJsSetup(
|
||||||
|
upgradeTask: String
|
||||||
|
) {
|
||||||
|
build(upgradeTask) {
|
||||||
|
assertTasksExecuted(":$upgradeTask")
|
||||||
|
assertConfigurationCacheStored()
|
||||||
|
}
|
||||||
|
|
||||||
|
build(upgradeTask) {
|
||||||
|
assertTasksUpToDate(":$upgradeTask")
|
||||||
|
assertConfigurationCacheReused()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+43
-281
@@ -12,12 +12,15 @@ import org.gradle.testkit.runner.BuildResult
|
|||||||
import org.gradle.util.GradleVersion
|
import org.gradle.util.GradleVersion
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.Distribution
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.Distribution
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.ir.KLIB_TYPE
|
import org.jetbrains.kotlin.gradle.targets.js.ir.KLIB_TYPE
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.LockCopyTask
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.LockCopyTask.Companion.PACKAGE_LOCK_MISMATCH_MESSAGE
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.LockCopyTask.Companion.RESTORE_PACKAGE_LOCK_NAME
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.LockCopyTask.Companion.STORE_PACKAGE_LOCK_NAME
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.LockCopyTask.Companion.UPGRADE_PACKAGE_LOCK
|
||||||
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.PackageJson
|
import org.jetbrains.kotlin.gradle.targets.js.npm.PackageJson
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.fromSrcPackageJson
|
import org.jetbrains.kotlin.gradle.targets.js.npm.fromSrcPackageJson
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockCopyTask.Companion.STORE_YARN_LOCK_NAME
|
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockCopyTask.Companion.UPGRADE_YARN_LOCK
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockCopyTask.Companion.YARN_LOCK_MISMATCH_MESSAGE
|
|
||||||
import org.jetbrains.kotlin.gradle.testbase.*
|
import org.jetbrains.kotlin.gradle.testbase.*
|
||||||
import org.jetbrains.kotlin.gradle.testbase.TestVersions.Gradle.G_7_6
|
import org.jetbrains.kotlin.gradle.testbase.TestVersions.Gradle.G_7_6
|
||||||
import org.jetbrains.kotlin.gradle.util.replaceText
|
import org.jetbrains.kotlin.gradle.util.replaceText
|
||||||
@@ -34,6 +37,7 @@ import kotlin.test.assertTrue
|
|||||||
@JsGradlePluginTests
|
@JsGradlePluginTests
|
||||||
class Kotlin2JsIrGradlePluginIT : KGPBaseTest() {
|
class Kotlin2JsIrGradlePluginIT : KGPBaseTest() {
|
||||||
|
|
||||||
|
|
||||||
@DisplayName("TS type declarations are generated")
|
@DisplayName("TS type declarations are generated")
|
||||||
@GradleTest
|
@GradleTest
|
||||||
fun generateDts(gradleVersion: GradleVersion) {
|
fun generateDts(gradleVersion: GradleVersion) {
|
||||||
@@ -171,37 +175,6 @@ class Kotlin2JsIrGradlePluginIT : KGPBaseTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@DisplayName("js composite build works with yarn.lock persistence")
|
|
||||||
@GradleTest
|
|
||||||
@GradleTestVersions(minVersion = G_7_6)
|
|
||||||
fun testJsCompositeBuildWithUpgradeYarnLock(gradleVersion: GradleVersion) {
|
|
||||||
project("js-composite-build", gradleVersion) {
|
|
||||||
buildGradleKts.modify(::transformBuildScriptWithPluginsDsl)
|
|
||||||
|
|
||||||
subProject("lib").apply {
|
|
||||||
buildGradleKts.modify(::transformBuildScriptWithPluginsDsl)
|
|
||||||
}
|
|
||||||
|
|
||||||
subProject("base").apply {
|
|
||||||
buildGradleKts.modify(::transformBuildScriptWithPluginsDsl)
|
|
||||||
}
|
|
||||||
|
|
||||||
build("kotlinUpgradeYarnLock") {
|
|
||||||
assertTasksExecuted(":base:publicPackageJson")
|
|
||||||
assertTasksExecuted(":lib:lib-2:publicPackageJson")
|
|
||||||
assertTasksExecuted(":kotlinNpmInstall")
|
|
||||||
assertTasksExecuted(":kotlinUpgradeYarnLock")
|
|
||||||
}
|
|
||||||
|
|
||||||
build(":nodeTest") {
|
|
||||||
assertTasksUpToDate(":base:publicPackageJson")
|
|
||||||
assertTasksUpToDate(":lib:lib-2:publicPackageJson")
|
|
||||||
assertTasksUpToDate(":kotlinNpmInstall")
|
|
||||||
assertTasksExecuted(":kotlinStoreYarnLock")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@GradleTest
|
@GradleTest
|
||||||
fun testJsIrIncrementalInParallel(gradleVersion: GradleVersion) {
|
fun testJsIrIncrementalInParallel(gradleVersion: GradleVersion) {
|
||||||
project("kotlin-js-browser-project", gradleVersion) {
|
project("kotlin-js-browser-project", gradleVersion) {
|
||||||
@@ -1029,7 +1002,15 @@ class Kotlin2JsIrGradlePluginIT : KGPBaseTest() {
|
|||||||
@DisplayName("public NPM dependencies are included into package.json")
|
@DisplayName("public NPM dependencies are included into package.json")
|
||||||
@GradleTest
|
@GradleTest
|
||||||
fun testPackageJsonWithPublicNpmDependencies(gradleVersion: GradleVersion) {
|
fun testPackageJsonWithPublicNpmDependencies(gradleVersion: GradleVersion) {
|
||||||
project("npm-dependencies", gradleVersion) {
|
project(
|
||||||
|
"npm-dependencies",
|
||||||
|
gradleVersion,
|
||||||
|
buildOptions = defaultBuildOptions.copy(
|
||||||
|
jsOptions = defaultBuildOptions.jsOptions?.copy(
|
||||||
|
yarn = false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) {
|
||||||
build("jsJar") {
|
build("jsJar") {
|
||||||
val archive = projectPath
|
val archive = projectPath
|
||||||
.resolve("build/libs")
|
.resolve("build/libs")
|
||||||
@@ -1097,8 +1078,8 @@ class Kotlin2JsIrGradlePluginIT : KGPBaseTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
build(UPGRADE_YARN_LOCK) {
|
build(UPGRADE_PACKAGE_LOCK) {
|
||||||
assertTasksExecuted(":$UPGRADE_YARN_LOCK")
|
assertTasksExecuted(":$UPGRADE_PACKAGE_LOCK")
|
||||||
}
|
}
|
||||||
|
|
||||||
build("jsJar") {
|
build("jsJar") {
|
||||||
@@ -1216,10 +1197,18 @@ class Kotlin2JsIrGradlePluginIT : KGPBaseTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@DisplayName("yarn resolutions works")
|
@DisplayName("npm overrides works")
|
||||||
@GradleTest
|
@GradleTest
|
||||||
fun testYarnResolution(gradleVersion: GradleVersion) {
|
fun testNpmOverrides(gradleVersion: GradleVersion) {
|
||||||
project("kotlin-js-yarn-resolutions", gradleVersion) {
|
project(
|
||||||
|
"kotlin-js-npm-overrides",
|
||||||
|
gradleVersion,
|
||||||
|
buildOptions = defaultBuildOptions.copy(
|
||||||
|
jsOptions = defaultBuildOptions.jsOptions?.copy(
|
||||||
|
yarn = false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) {
|
||||||
build("packageJson", "rootPackageJson", "kotlinNpmInstall") {
|
build("packageJson", "rootPackageJson", "kotlinNpmInstall") {
|
||||||
fun getPackageJson() =
|
fun getPackageJson() =
|
||||||
projectPath.resolve("build/js")
|
projectPath.resolve("build/js")
|
||||||
@@ -1229,16 +1218,16 @@ class Kotlin2JsIrGradlePluginIT : KGPBaseTest() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val name = "lodash"
|
val name = "lodash"
|
||||||
val version = getPackageJson().resolutions?.get(name)
|
val version = getPackageJson().overrides?.get(name)
|
||||||
val requiredVersion = ">=1.0.0 <1.2.1 || >1.4.0 <2.0.0"
|
val requiredVersion = ">=1.0.0 <1.2.1 || >1.4.0 <2.0.0"
|
||||||
assertTrue("Root package.json must have resolution $name with version $requiredVersion, but $version found") {
|
assertTrue("Root package.json must override $name with version $requiredVersion, but $version found") {
|
||||||
version == requiredVersion
|
version == requiredVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
val react = "react"
|
val react = "react"
|
||||||
val reactVersion = getPackageJson().resolutions?.get(react)
|
val reactVersion = getPackageJson().overrides?.get(react)
|
||||||
val requiredReactVersion = "16.0.0"
|
val requiredReactVersion = "16.0.0"
|
||||||
assertTrue("Root package.json must have resolution $react with version $requiredReactVersion, but $reactVersion found") {
|
assertTrue("Root package.json must override $react with version $requiredReactVersion, but $reactVersion found") {
|
||||||
reactVersion == requiredReactVersion
|
reactVersion == requiredReactVersion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1374,176 +1363,6 @@ class Kotlin2JsIrGradlePluginIT : KGPBaseTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@DisplayName("Failing with yarn.lock update")
|
|
||||||
@GradleTest
|
|
||||||
fun testFailingWithYarnLockUpdate(gradleVersion: GradleVersion) {
|
|
||||||
project("kotlin-js-yarn-lock-project", gradleVersion) {
|
|
||||||
build(STORE_YARN_LOCK_NAME) {
|
|
||||||
assertTasksExecuted(":$STORE_YARN_LOCK_NAME")
|
|
||||||
}
|
|
||||||
|
|
||||||
projectPath.resolve("kotlin-js-store").deleteRecursively()
|
|
||||||
|
|
||||||
buildGradleKts.modify {
|
|
||||||
it + "\n" +
|
|
||||||
"""
|
|
||||||
rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin::class.java) {
|
|
||||||
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().reportNewYarnLock = true
|
|
||||||
}
|
|
||||||
""".trimIndent()
|
|
||||||
}
|
|
||||||
|
|
||||||
buildAndFail(STORE_YARN_LOCK_NAME) {
|
|
||||||
assertTasksFailed(":$STORE_YARN_LOCK_NAME")
|
|
||||||
}
|
|
||||||
|
|
||||||
buildGradleKts.modify {
|
|
||||||
it + "\n" +
|
|
||||||
"""
|
|
||||||
dependencies {
|
|
||||||
implementation(npm("decamelize", "6.0.0"))
|
|
||||||
}
|
|
||||||
|
|
||||||
rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin::class.java) {
|
|
||||||
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().yarnLockMismatchReport =
|
|
||||||
org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockMismatchReport.FAIL
|
|
||||||
}
|
|
||||||
""".trimIndent()
|
|
||||||
}
|
|
||||||
|
|
||||||
buildAndFail(STORE_YARN_LOCK_NAME) {
|
|
||||||
assertTasksFailed(":$STORE_YARN_LOCK_NAME")
|
|
||||||
}
|
|
||||||
|
|
||||||
// yarn.lock was not updated
|
|
||||||
buildAndFail(STORE_YARN_LOCK_NAME) {
|
|
||||||
assertTasksFailed(":$STORE_YARN_LOCK_NAME")
|
|
||||||
}
|
|
||||||
|
|
||||||
build(UPGRADE_YARN_LOCK) {
|
|
||||||
assertTasksExecuted(":$UPGRADE_YARN_LOCK")
|
|
||||||
}
|
|
||||||
|
|
||||||
buildGradleKts.modify {
|
|
||||||
val replaced = it.replace("implementation(npm(\"decamelize\", \"6.0.0\"))", "")
|
|
||||||
replaced + "\n" +
|
|
||||||
"""
|
|
||||||
rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin::class.java) {
|
|
||||||
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().yarnLockMismatchReport =
|
|
||||||
org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockMismatchReport.WARNING
|
|
||||||
}
|
|
||||||
""".trimIndent()
|
|
||||||
}
|
|
||||||
|
|
||||||
build(STORE_YARN_LOCK_NAME) {
|
|
||||||
assertTasksExecuted(":$STORE_YARN_LOCK_NAME")
|
|
||||||
|
|
||||||
assertOutputContains(YARN_LOCK_MISMATCH_MESSAGE)
|
|
||||||
}
|
|
||||||
|
|
||||||
build(UPGRADE_YARN_LOCK) {
|
|
||||||
assertTasksExecuted(":$UPGRADE_YARN_LOCK")
|
|
||||||
}
|
|
||||||
|
|
||||||
buildGradleKts.modify {
|
|
||||||
it + "\n" +
|
|
||||||
"""
|
|
||||||
dependencies {
|
|
||||||
implementation(npm("decamelize", "6.0.0"))
|
|
||||||
}
|
|
||||||
|
|
||||||
rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin::class.java) {
|
|
||||||
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().yarnLockMismatchReport =
|
|
||||||
org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockMismatchReport.NONE
|
|
||||||
}
|
|
||||||
""".trimIndent()
|
|
||||||
}
|
|
||||||
|
|
||||||
build(STORE_YARN_LOCK_NAME) {
|
|
||||||
assertTasksExecuted(":$STORE_YARN_LOCK_NAME")
|
|
||||||
|
|
||||||
assertOutputDoesNotContain(YARN_LOCK_MISMATCH_MESSAGE)
|
|
||||||
}
|
|
||||||
|
|
||||||
build(UPGRADE_YARN_LOCK) {
|
|
||||||
assertTasksExecuted(":$UPGRADE_YARN_LOCK")
|
|
||||||
}
|
|
||||||
|
|
||||||
buildGradleKts.modify {
|
|
||||||
it.replace("implementation(npm(\"decamelize\", \"6.0.0\"))", "")
|
|
||||||
}
|
|
||||||
|
|
||||||
projectPath.resolve("kotlin-js-store").deleteRecursively()
|
|
||||||
|
|
||||||
buildGradleKts.modify {
|
|
||||||
it + "\n" +
|
|
||||||
"""
|
|
||||||
rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin::class.java) {
|
|
||||||
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().yarnLockMismatchReport =
|
|
||||||
org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockMismatchReport.NONE
|
|
||||||
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().reportNewYarnLock =
|
|
||||||
true
|
|
||||||
}
|
|
||||||
""".trimIndent()
|
|
||||||
}
|
|
||||||
|
|
||||||
build(STORE_YARN_LOCK_NAME) {
|
|
||||||
assertTasksExecuted(":$STORE_YARN_LOCK_NAME")
|
|
||||||
|
|
||||||
assertOutputDoesNotContain(YARN_LOCK_MISMATCH_MESSAGE)
|
|
||||||
}
|
|
||||||
|
|
||||||
buildGradleKts.modify {
|
|
||||||
it + "\n" +
|
|
||||||
"""
|
|
||||||
dependencies {
|
|
||||||
implementation(npm("decamelize", "6.0.0"))
|
|
||||||
}
|
|
||||||
|
|
||||||
rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin::class.java) {
|
|
||||||
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().yarnLockMismatchReport =
|
|
||||||
org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockMismatchReport.FAIL
|
|
||||||
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().yarnLockAutoReplace =
|
|
||||||
true
|
|
||||||
}
|
|
||||||
""".trimIndent()
|
|
||||||
}
|
|
||||||
|
|
||||||
buildAndFail(STORE_YARN_LOCK_NAME) {
|
|
||||||
assertTasksFailed(":$STORE_YARN_LOCK_NAME")
|
|
||||||
}
|
|
||||||
|
|
||||||
//yarn.lock was updated
|
|
||||||
build(STORE_YARN_LOCK_NAME) {
|
|
||||||
assertTasksExecuted(":$STORE_YARN_LOCK_NAME")
|
|
||||||
}
|
|
||||||
|
|
||||||
buildGradleKts.modify {
|
|
||||||
it.replace("implementation(npm(\"decamelize\", \"6.0.0\"))", "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if everything ok without build/js/yarn.lock
|
|
||||||
build("clean") {
|
|
||||||
assertTasksExecuted(":clean")
|
|
||||||
}
|
|
||||||
|
|
||||||
build("clean") {
|
|
||||||
assertTasksUpToDate(":clean")
|
|
||||||
}
|
|
||||||
|
|
||||||
buildAndFail(STORE_YARN_LOCK_NAME) {
|
|
||||||
assertTasksFailed(":$STORE_YARN_LOCK_NAME")
|
|
||||||
}
|
|
||||||
|
|
||||||
projectPath.resolve("kotlin-js-store").deleteRecursively()
|
|
||||||
|
|
||||||
//check if independent tasks can be executed
|
|
||||||
build("help") {
|
|
||||||
assertTasksExecuted(":help")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@DisplayName("webpack configuration is valid")
|
@DisplayName("webpack configuration is valid")
|
||||||
@GradleTest
|
@GradleTest
|
||||||
fun testWebpackConfig(gradleVersion: GradleVersion) {
|
fun testWebpackConfig(gradleVersion: GradleVersion) {
|
||||||
@@ -1622,7 +1441,15 @@ class Kotlin2JsIrGradlePluginIT : KGPBaseTest() {
|
|||||||
@DisplayName("Disable download should not download Node.JS and Yarn")
|
@DisplayName("Disable download should not download Node.JS and Yarn")
|
||||||
@GradleTest
|
@GradleTest
|
||||||
fun testNodeJsAndYarnNotDownloaded(gradleVersion: GradleVersion) {
|
fun testNodeJsAndYarnNotDownloaded(gradleVersion: GradleVersion) {
|
||||||
project("nodeJsDownload", gradleVersion) {
|
project(
|
||||||
|
"nodeJsDownload",
|
||||||
|
gradleVersion,
|
||||||
|
buildOptions = defaultBuildOptions.copy(
|
||||||
|
jsOptions = defaultBuildOptions.jsOptions?.copy(
|
||||||
|
yarn = true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) {
|
||||||
buildGradleKts.modify {
|
buildGradleKts.modify {
|
||||||
it + "\n" +
|
it + "\n" +
|
||||||
"""
|
"""
|
||||||
@@ -1640,71 +1467,6 @@ class Kotlin2JsIrGradlePluginIT : KGPBaseTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@DisplayName("Yarn.lock persistence")
|
|
||||||
@GradleTest
|
|
||||||
fun testYarnLockStore(gradleVersion: GradleVersion) {
|
|
||||||
project("nodeJsDownload", gradleVersion) {
|
|
||||||
build("assemble", "kotlinStoreYarnLock") {
|
|
||||||
assertFileExists(projectPath.resolve("kotlin-js-store").resolve("yarn.lock"))
|
|
||||||
assert(
|
|
||||||
projectPath
|
|
||||||
.resolve("kotlin-js-store")
|
|
||||||
.resolve("yarn.lock")
|
|
||||||
.readText() == projectPath.resolve("build/js/yarn.lock").readText()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@DisplayName("Yarn ignore scripts")
|
|
||||||
@GradleTest
|
|
||||||
fun testYarnIgnoreScripts(gradleVersion: GradleVersion) {
|
|
||||||
project("nodeJsDownload", gradleVersion) {
|
|
||||||
buildGradleKts.modify {
|
|
||||||
it + "\n" +
|
|
||||||
"""
|
|
||||||
dependencies {
|
|
||||||
implementation(npm("puppeteer", "11.0.0"))
|
|
||||||
}
|
|
||||||
""".trimIndent()
|
|
||||||
}
|
|
||||||
build("assemble", "kotlinNpmInstall") {
|
|
||||||
assert(
|
|
||||||
projectPath
|
|
||||||
.resolve("build")
|
|
||||||
.resolve("js")
|
|
||||||
.resolve("node_modules")
|
|
||||||
.resolve("puppeteer")
|
|
||||||
.resolve(".local-chromium")
|
|
||||||
.notExists()
|
|
||||||
) {
|
|
||||||
"Chromium should not be installed with --ignore-scripts"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buildGradleKts.modify {
|
|
||||||
it + "\n" +
|
|
||||||
"""
|
|
||||||
rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin> {
|
|
||||||
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().ignoreScripts = false
|
|
||||||
}
|
|
||||||
""".trimIndent()
|
|
||||||
}
|
|
||||||
|
|
||||||
build("clean")
|
|
||||||
|
|
||||||
build("assemble", "kotlinNpmInstall") {
|
|
||||||
assertDirectoryExists(
|
|
||||||
projectPath
|
|
||||||
.resolve("build")
|
|
||||||
.resolve("js")
|
|
||||||
.resolve("node_modules")
|
|
||||||
.resolve("puppeteer")
|
|
||||||
.resolve(".local-chromium")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@DisplayName("js files from dependency are installed")
|
@DisplayName("js files from dependency are installed")
|
||||||
@GradleTest
|
@GradleTest
|
||||||
fun testKotlinJsDependencyWithJsFiles(gradleVersion: GradleVersion) {
|
fun testKotlinJsDependencyWithJsFiles(gradleVersion: GradleVersion) {
|
||||||
@@ -1754,7 +1516,7 @@ class Kotlin2JsIrGradlePluginIT : KGPBaseTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@DisplayName("test package.jsom skipped with main package.json was up-to-date")
|
@DisplayName("test package.json skipped with main package.json was up-to-date")
|
||||||
@GradleTest
|
@GradleTest
|
||||||
fun testPackageJsonSkippedWithUpToDatePackageJsons(gradleVersion: GradleVersion) {
|
fun testPackageJsonSkippedWithUpToDatePackageJsons(gradleVersion: GradleVersion) {
|
||||||
project("kotlin-js-browser-library-project", gradleVersion) {
|
project("kotlin-js-browser-library-project", gradleVersion) {
|
||||||
|
|||||||
+464
@@ -0,0 +1,464 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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
|
||||||
|
|
||||||
|
import org.gradle.util.GradleVersion
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.LockCopyTask
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.LockCopyTask.Companion.PACKAGE_LOCK_MISMATCH_MESSAGE
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.LockCopyTask.Companion.RESTORE_PACKAGE_LOCK_NAME
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.LockCopyTask.Companion.STORE_PACKAGE_LOCK_NAME
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.LockCopyTask.Companion.UPGRADE_PACKAGE_LOCK
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin
|
||||||
|
import org.jetbrains.kotlin.gradle.testbase.*
|
||||||
|
import org.jetbrains.kotlin.gradle.testbase.TestVersions.Gradle.G_7_6
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
import kotlin.io.path.deleteRecursively
|
||||||
|
import kotlin.io.path.notExists
|
||||||
|
import kotlin.io.path.readText
|
||||||
|
|
||||||
|
class NpmGradlePluginIT : PackageManagerGradlePluginIT() {
|
||||||
|
override val yarn: Boolean = false
|
||||||
|
|
||||||
|
override val plugin = "nodejs.NodeJsRootPlugin"
|
||||||
|
|
||||||
|
override val extension = "npm.NpmExtension"
|
||||||
|
|
||||||
|
override val upgradeTaskName: String = UPGRADE_PACKAGE_LOCK
|
||||||
|
|
||||||
|
override val storeTaskName = STORE_PACKAGE_LOCK_NAME
|
||||||
|
|
||||||
|
override val restoreTaskName = RESTORE_PACKAGE_LOCK_NAME
|
||||||
|
|
||||||
|
override val reportNewLockFile = "reportNewPackageLock"
|
||||||
|
|
||||||
|
override val lockMismatchReport = "packageLockMismatchReport"
|
||||||
|
|
||||||
|
override val lockFileAutoReplace = "packageLockAutoReplace"
|
||||||
|
|
||||||
|
override val mismatchReportType = "npm.LockFileMismatchReport"
|
||||||
|
|
||||||
|
override val lockFileName: String = LockCopyTask.PACKAGE_LOCK
|
||||||
|
|
||||||
|
override val setProperty: (String) -> String = { ".set($it)" }
|
||||||
|
}
|
||||||
|
|
||||||
|
class YarnGradlePluginIT : PackageManagerGradlePluginIT() {
|
||||||
|
override val yarn: Boolean = true
|
||||||
|
|
||||||
|
override val plugin: String = "yarn.YarnPlugin"
|
||||||
|
|
||||||
|
override val extension: String = "yarn.YarnRootExtension"
|
||||||
|
|
||||||
|
override val upgradeTaskName: String = YarnPlugin.UPGRADE_YARN_LOCK
|
||||||
|
|
||||||
|
override val storeTaskName = YarnPlugin.STORE_YARN_LOCK_NAME
|
||||||
|
|
||||||
|
override val restoreTaskName: String = YarnPlugin.RESTORE_YARN_LOCK_NAME
|
||||||
|
|
||||||
|
override val reportNewLockFile: String = "reportNewYarnLock"
|
||||||
|
|
||||||
|
override val lockMismatchReport: String = "yarnLockMismatchReport"
|
||||||
|
|
||||||
|
override val lockFileAutoReplace: String = "yarnLockAutoReplace"
|
||||||
|
|
||||||
|
override val mismatchReportType: String = "yarn.YarnLockMismatchReport"
|
||||||
|
|
||||||
|
override val lockFileName: String = LockCopyTask.YARN_LOCK
|
||||||
|
|
||||||
|
override val setProperty: (String) -> String = { " = $it" }
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsGradlePluginTests
|
||||||
|
abstract class PackageManagerGradlePluginIT : KGPBaseTest() {
|
||||||
|
|
||||||
|
abstract val yarn: Boolean
|
||||||
|
|
||||||
|
abstract val plugin: String
|
||||||
|
|
||||||
|
abstract val extension: String
|
||||||
|
|
||||||
|
abstract val upgradeTaskName: String
|
||||||
|
|
||||||
|
abstract val storeTaskName: String
|
||||||
|
|
||||||
|
abstract val restoreTaskName: String
|
||||||
|
|
||||||
|
abstract val reportNewLockFile: String
|
||||||
|
|
||||||
|
abstract val lockMismatchReport: String
|
||||||
|
|
||||||
|
abstract val lockFileAutoReplace: String
|
||||||
|
|
||||||
|
abstract val mismatchReportType: String
|
||||||
|
|
||||||
|
abstract val lockFileName: String
|
||||||
|
|
||||||
|
abstract val setProperty: (String) -> String
|
||||||
|
|
||||||
|
override val defaultBuildOptions: BuildOptions
|
||||||
|
get() = super.defaultBuildOptions.copy(
|
||||||
|
jsOptions = super.defaultBuildOptions.jsOptions?.copy(
|
||||||
|
yarn = yarn
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
@DisplayName("js composite build works with lock file persistence")
|
||||||
|
@GradleTest
|
||||||
|
@GradleTestVersions(minVersion = G_7_6)
|
||||||
|
fun testJsCompositeBuildWithUpgradeLockFile(gradleVersion: GradleVersion) {
|
||||||
|
project("js-composite-build", gradleVersion) {
|
||||||
|
testJsCompositeBuildWithUpgradeLockFile(
|
||||||
|
upgradeTaskName,
|
||||||
|
storeTaskName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun TestProject.testJsCompositeBuildWithUpgradeLockFile(
|
||||||
|
upgradeTask: String,
|
||||||
|
storeTask: String,
|
||||||
|
) {
|
||||||
|
buildGradleKts.modify(::transformBuildScriptWithPluginsDsl)
|
||||||
|
|
||||||
|
subProject("lib").apply {
|
||||||
|
buildGradleKts.modify(::transformBuildScriptWithPluginsDsl)
|
||||||
|
}
|
||||||
|
|
||||||
|
subProject("base").apply {
|
||||||
|
buildGradleKts.modify(::transformBuildScriptWithPluginsDsl)
|
||||||
|
}
|
||||||
|
|
||||||
|
build(upgradeTask) {
|
||||||
|
assertTasksExecuted(":base:publicPackageJson")
|
||||||
|
assertTasksExecuted(":lib:lib-2:publicPackageJson")
|
||||||
|
assertTasksExecuted(":kotlinNpmInstall")
|
||||||
|
assertTasksExecuted(":$upgradeTask")
|
||||||
|
}
|
||||||
|
|
||||||
|
build(":nodeTest") {
|
||||||
|
assertTasksUpToDate(":base:publicPackageJson")
|
||||||
|
assertTasksUpToDate(":lib:lib-2:publicPackageJson")
|
||||||
|
assertTasksUpToDate(":kotlinNpmInstall")
|
||||||
|
assertTasksExecuted(":$storeTask")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("Failing with lock file update")
|
||||||
|
@GradleTest
|
||||||
|
fun testFailingWithLockFileUpdate(gradleVersion: GradleVersion) {
|
||||||
|
project("kotlin-js-package-lock-project", gradleVersion) {
|
||||||
|
testFailingWithLockFileUpdate(
|
||||||
|
storeTaskName = storeTaskName,
|
||||||
|
restoreTaskName = restoreTaskName,
|
||||||
|
upgradeTaskName = upgradeTaskName,
|
||||||
|
extension = extension,
|
||||||
|
reportNewLockFile = reportNewLockFile,
|
||||||
|
lockMismatchReport = lockMismatchReport,
|
||||||
|
lockFileAutoReplace = lockFileAutoReplace,
|
||||||
|
mismatchReport = mismatchReportType,
|
||||||
|
set = setProperty
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun TestProject.testFailingWithLockFileUpdate(
|
||||||
|
storeTaskName: String,
|
||||||
|
restoreTaskName: String,
|
||||||
|
upgradeTaskName: String,
|
||||||
|
extension: String,
|
||||||
|
reportNewLockFile: String,
|
||||||
|
lockMismatchReport: String,
|
||||||
|
lockFileAutoReplace: String,
|
||||||
|
mismatchReport: String,
|
||||||
|
set: (String) -> String,
|
||||||
|
) {
|
||||||
|
build(storeTaskName) {
|
||||||
|
assertTasksSkipped(":$restoreTaskName")
|
||||||
|
assertTasksExecuted(":$storeTaskName")
|
||||||
|
}
|
||||||
|
|
||||||
|
projectPath.resolve(LockCopyTask.KOTLIN_JS_STORE).deleteRecursively()
|
||||||
|
|
||||||
|
buildGradleKts.modify {
|
||||||
|
it + "\n" +
|
||||||
|
"""
|
||||||
|
rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin::class.java) {
|
||||||
|
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.$extension>().$reportNewLockFile${set("true")}
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
}
|
||||||
|
|
||||||
|
buildAndFail(storeTaskName) {
|
||||||
|
assertTasksSkipped(":$restoreTaskName")
|
||||||
|
assertTasksFailed(":$storeTaskName")
|
||||||
|
}
|
||||||
|
|
||||||
|
buildGradleKts.modify {
|
||||||
|
it + "\n" +
|
||||||
|
"""
|
||||||
|
dependencies {
|
||||||
|
implementation(npm("decamelize", "6.0.0"))
|
||||||
|
}
|
||||||
|
|
||||||
|
rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin::class.java) {
|
||||||
|
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.$extension>().$lockMismatchReport${
|
||||||
|
set(
|
||||||
|
"org.jetbrains.kotlin.gradle.targets.js.$mismatchReport.FAIL"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
}
|
||||||
|
|
||||||
|
buildAndFail(storeTaskName) {
|
||||||
|
assertTasksExecuted(":$restoreTaskName")
|
||||||
|
assertTasksFailed(":$storeTaskName")
|
||||||
|
}
|
||||||
|
|
||||||
|
// yarn.lock was not updated
|
||||||
|
buildAndFail(storeTaskName) {
|
||||||
|
assertTasksExecuted(":$restoreTaskName")
|
||||||
|
assertTasksFailed(":$storeTaskName")
|
||||||
|
}
|
||||||
|
|
||||||
|
build(upgradeTaskName) {
|
||||||
|
assertTasksExecuted(":$restoreTaskName")
|
||||||
|
assertTasksExecuted(":$upgradeTaskName")
|
||||||
|
}
|
||||||
|
|
||||||
|
buildGradleKts.modify {
|
||||||
|
val replaced = it.replace("implementation(npm(\"decamelize\", \"6.0.0\"))", "")
|
||||||
|
replaced + "\n" +
|
||||||
|
"""
|
||||||
|
rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin::class.java) {
|
||||||
|
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.$extension>().$lockMismatchReport${
|
||||||
|
set(
|
||||||
|
"org.jetbrains.kotlin.gradle.targets.js.$mismatchReport.WARNING"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
}
|
||||||
|
|
||||||
|
build(storeTaskName) {
|
||||||
|
assertTasksExecuted(":$restoreTaskName")
|
||||||
|
assertTasksExecuted(":$storeTaskName")
|
||||||
|
|
||||||
|
assertOutputContains(PACKAGE_LOCK_MISMATCH_MESSAGE)
|
||||||
|
}
|
||||||
|
|
||||||
|
build(upgradeTaskName) {
|
||||||
|
assertTasksExecuted(":$restoreTaskName")
|
||||||
|
assertTasksExecuted(":$upgradeTaskName")
|
||||||
|
}
|
||||||
|
|
||||||
|
buildGradleKts.modify {
|
||||||
|
it + "\n" +
|
||||||
|
"""
|
||||||
|
dependencies {
|
||||||
|
implementation(npm("decamelize", "6.0.0"))
|
||||||
|
}
|
||||||
|
|
||||||
|
rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin::class.java) {
|
||||||
|
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.$extension>().$lockMismatchReport${
|
||||||
|
set(
|
||||||
|
"org.jetbrains.kotlin.gradle.targets.js.$mismatchReport.NONE"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
}
|
||||||
|
|
||||||
|
build(storeTaskName) {
|
||||||
|
assertTasksExecuted(":$restoreTaskName")
|
||||||
|
assertTasksExecuted(":$storeTaskName")
|
||||||
|
|
||||||
|
assertOutputDoesNotContain(PACKAGE_LOCK_MISMATCH_MESSAGE)
|
||||||
|
}
|
||||||
|
|
||||||
|
build(upgradeTaskName) {
|
||||||
|
assertTasksExecuted(":$restoreTaskName")
|
||||||
|
assertTasksExecuted(":$upgradeTaskName")
|
||||||
|
}
|
||||||
|
|
||||||
|
buildGradleKts.modify {
|
||||||
|
it.replace("implementation(npm(\"decamelize\", \"6.0.0\"))", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
projectPath.resolve(LockCopyTask.KOTLIN_JS_STORE).deleteRecursively()
|
||||||
|
|
||||||
|
buildGradleKts.modify {
|
||||||
|
it + "\n" +
|
||||||
|
"""
|
||||||
|
rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin::class.java) {
|
||||||
|
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.$extension>().$lockMismatchReport${
|
||||||
|
set(
|
||||||
|
"org.jetbrains.kotlin.gradle.targets.js.$mismatchReport.NONE"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.$extension>().$reportNewLockFile${
|
||||||
|
set(
|
||||||
|
"true"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
}
|
||||||
|
|
||||||
|
build(storeTaskName) {
|
||||||
|
assertTasksSkipped(":$restoreTaskName")
|
||||||
|
assertTasksExecuted(":$storeTaskName")
|
||||||
|
|
||||||
|
assertOutputDoesNotContain(PACKAGE_LOCK_MISMATCH_MESSAGE)
|
||||||
|
}
|
||||||
|
|
||||||
|
buildGradleKts.modify {
|
||||||
|
it + "\n" +
|
||||||
|
"""
|
||||||
|
dependencies {
|
||||||
|
implementation(npm("decamelize", "6.0.0"))
|
||||||
|
}
|
||||||
|
|
||||||
|
rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin::class.java) {
|
||||||
|
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.$extension>().$lockMismatchReport${
|
||||||
|
set(
|
||||||
|
"org.jetbrains.kotlin.gradle.targets.js.$mismatchReport.FAIL"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.$extension>().$lockFileAutoReplace${
|
||||||
|
set(
|
||||||
|
"true"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
}
|
||||||
|
|
||||||
|
buildAndFail(storeTaskName) {
|
||||||
|
assertTasksUpToDate(":$restoreTaskName")
|
||||||
|
assertTasksFailed(":$storeTaskName")
|
||||||
|
}
|
||||||
|
|
||||||
|
//yarn.lock was updated
|
||||||
|
build(storeTaskName) {
|
||||||
|
assertTasksExecuted(":$restoreTaskName")
|
||||||
|
assertTasksExecuted(":$storeTaskName")
|
||||||
|
}
|
||||||
|
|
||||||
|
buildGradleKts.modify {
|
||||||
|
it.replace("implementation(npm(\"decamelize\", \"6.0.0\"))", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if everything ok without build/js/yarn.lock
|
||||||
|
build("clean") {
|
||||||
|
assertTasksExecuted(":clean")
|
||||||
|
}
|
||||||
|
|
||||||
|
build("clean") {
|
||||||
|
assertTasksUpToDate(":clean")
|
||||||
|
}
|
||||||
|
|
||||||
|
buildAndFail(storeTaskName) {
|
||||||
|
assertTasksExecuted(":$restoreTaskName")
|
||||||
|
assertTasksFailed(":$storeTaskName")
|
||||||
|
}
|
||||||
|
|
||||||
|
projectPath.resolve(LockCopyTask.KOTLIN_JS_STORE).deleteRecursively()
|
||||||
|
|
||||||
|
//check if independent tasks can be executed
|
||||||
|
build("help") {
|
||||||
|
assertTasksExecuted(":help")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("Lock file persistence")
|
||||||
|
@GradleTest
|
||||||
|
fun testLockStore(gradleVersion: GradleVersion) {
|
||||||
|
project("nodeJsDownload", gradleVersion) {
|
||||||
|
testLockStore(
|
||||||
|
storeTaskName,
|
||||||
|
lockFileName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun TestProject.testLockStore(
|
||||||
|
taskName: String,
|
||||||
|
lockFile: String,
|
||||||
|
) {
|
||||||
|
build("assemble", taskName) {
|
||||||
|
assertFileExists(projectPath.resolve(LockCopyTask.KOTLIN_JS_STORE).resolve(lockFile))
|
||||||
|
assert(
|
||||||
|
projectPath
|
||||||
|
.resolve(LockCopyTask.KOTLIN_JS_STORE)
|
||||||
|
.resolve(lockFile)
|
||||||
|
.readText() == projectPath.resolve("build/js/${lockFile}").readText()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("Package manager ignore scripts")
|
||||||
|
@GradleTest
|
||||||
|
fun testIgnoreScripts(gradleVersion: GradleVersion) {
|
||||||
|
project("nodeJsDownload", gradleVersion) {
|
||||||
|
testIgnoreScripts(
|
||||||
|
plugin,
|
||||||
|
extension,
|
||||||
|
setProperty
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun TestProject.testIgnoreScripts(
|
||||||
|
plugin: String,
|
||||||
|
extension: String,
|
||||||
|
set: (String) -> String,
|
||||||
|
) {
|
||||||
|
buildGradleKts.modify {
|
||||||
|
it + "\n" +
|
||||||
|
"""
|
||||||
|
dependencies {
|
||||||
|
implementation(npm("puppeteer", "11.0.0"))
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
}
|
||||||
|
build("assemble", "kotlinNpmInstall") {
|
||||||
|
assert(
|
||||||
|
projectPath
|
||||||
|
.resolve("build")
|
||||||
|
.resolve("js")
|
||||||
|
.resolve("node_modules")
|
||||||
|
.resolve("puppeteer")
|
||||||
|
.resolve(".local-chromium")
|
||||||
|
.notExists()
|
||||||
|
) {
|
||||||
|
"Chromium should not be installed with --ignore-scripts"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildGradleKts.modify {
|
||||||
|
it + "\n" +
|
||||||
|
"""
|
||||||
|
rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.$plugin> {
|
||||||
|
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.$extension>().ignoreScripts${set("false")}
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
}
|
||||||
|
|
||||||
|
build("clean")
|
||||||
|
|
||||||
|
build("assemble", "kotlinNpmInstall") {
|
||||||
|
assertDirectoryExists(
|
||||||
|
projectPath
|
||||||
|
.resolve("build")
|
||||||
|
.resolve("js")
|
||||||
|
.resolve("node_modules")
|
||||||
|
.resolve("puppeteer")
|
||||||
|
.resolve(".local-chromium")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-2
@@ -37,7 +37,7 @@ data class BuildOptions(
|
|||||||
val buildCacheEnabled: Boolean = false,
|
val buildCacheEnabled: Boolean = false,
|
||||||
val kaptOptions: KaptOptions? = null,
|
val kaptOptions: KaptOptions? = null,
|
||||||
val androidVersion: String? = null,
|
val androidVersion: String? = null,
|
||||||
val jsOptions: JsOptions? = null,
|
val jsOptions: JsOptions? = JsOptions(),
|
||||||
val buildReport: List<BuildReportType> = emptyList(),
|
val buildReport: List<BuildReportType> = emptyList(),
|
||||||
val usePreciseJavaTracking: Boolean? = null,
|
val usePreciseJavaTracking: Boolean? = null,
|
||||||
val languageVersion: String? = null,
|
val languageVersion: String? = null,
|
||||||
@@ -79,7 +79,8 @@ data class BuildOptions(
|
|||||||
data class JsOptions(
|
data class JsOptions(
|
||||||
val incrementalJs: Boolean? = null,
|
val incrementalJs: Boolean? = null,
|
||||||
val incrementalJsKlib: Boolean? = null,
|
val incrementalJsKlib: Boolean? = null,
|
||||||
val incrementalJsIr: Boolean? = null
|
val incrementalJsIr: Boolean? = null,
|
||||||
|
val yarn: Boolean? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
data class NativeOptions(
|
data class NativeOptions(
|
||||||
@@ -163,6 +164,7 @@ data class BuildOptions(
|
|||||||
jsOptions.incrementalJs?.let { arguments.add("-Pkotlin.incremental.js=$it") }
|
jsOptions.incrementalJs?.let { arguments.add("-Pkotlin.incremental.js=$it") }
|
||||||
jsOptions.incrementalJsKlib?.let { arguments.add("-Pkotlin.incremental.js.klib=$it") }
|
jsOptions.incrementalJsKlib?.let { arguments.add("-Pkotlin.incremental.js.klib=$it") }
|
||||||
jsOptions.incrementalJsIr?.let { arguments.add("-Pkotlin.incremental.js.ir=$it") }
|
jsOptions.incrementalJsIr?.let { arguments.add("-Pkotlin.incremental.js.ir=$it") }
|
||||||
|
jsOptions.yarn?.let { arguments.add("-Pkotlin.js.yarn=$it") }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (androidVersion != null) {
|
if (androidVersion != null) {
|
||||||
|
|||||||
+4
@@ -1,3 +1,5 @@
|
|||||||
|
import org.jetbrains.kotlin.gradle.targets.js.yarn.yarn
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("js")
|
kotlin("js")
|
||||||
}
|
}
|
||||||
@@ -10,6 +12,8 @@ kotlin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
yarn
|
||||||
|
|
||||||
rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin> {
|
rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin> {
|
||||||
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension>().downloadBaseUrl = null
|
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension>().downloadBaseUrl = null
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -10,13 +10,13 @@ repositories {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin::class.java) {
|
rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin::class.java) {
|
||||||
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().apply {
|
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.npm.NpmExtension>().apply {
|
||||||
resolution("lodash") {
|
override("lodash") {
|
||||||
include("^1.0.0")
|
include("^1.0.0")
|
||||||
exclude("~1.2.1", "1.3.0 - 1.4.0")
|
exclude("~1.2.1", "1.3.0 - 1.4.0")
|
||||||
}
|
}
|
||||||
resolution("react", "16.0.0")
|
override("react", "16.0.0")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
rootProject.name = "kotlin-js-npm-overrides"
|
||||||
|
|
||||||
|
include("base")
|
||||||
|
include("lib")
|
||||||
-4
@@ -1,4 +0,0 @@
|
|||||||
rootProject.name = "kotlin-js-yarn-resolutions"
|
|
||||||
|
|
||||||
include("base")
|
|
||||||
include("lib")
|
|
||||||
+2
-2
@@ -25,9 +25,9 @@ allprojects.forEach {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockCopyTask>("kotlinStoreYarnLock") {
|
tasks.named<org.jetbrains.kotlin.gradle.targets.js.npm.LockCopyTask>("kotlinStorePackageLock") {
|
||||||
//A little hacky way to make yarn results
|
//A little hacky way to make yarn results
|
||||||
inputFile.fileValue(projectDir.resolve("yarnLockStub"))
|
inputFile.fileValue(projectDir.resolve("packageLockStub"))
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
|
|||||||
+2
-2
@@ -5,9 +5,9 @@ plugins {
|
|||||||
rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin> {
|
rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin> {
|
||||||
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension>().nodeVersion = "20.2.0"
|
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension>().nodeVersion = "20.2.0"
|
||||||
|
|
||||||
tasks.named<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockCopyTask>("kotlinStoreYarnLock") {
|
tasks.named<org.jetbrains.kotlin.gradle.targets.js.npm.LockCopyTask>("kotlinStorePackageLock") {
|
||||||
//A little hacky way to make yarn results
|
//A little hacky way to make yarn results
|
||||||
inputFile.fileValue(projectDir.resolve("yarnLockStub"))
|
inputFile.fileValue(projectDir.resolve("packageLockStub"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -20,9 +20,9 @@ allprojects.forEach {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockCopyTask>("kotlinStoreYarnLock") {
|
tasks.named<org.jetbrains.kotlin.gradle.targets.js.npm.LockCopyTask>("kotlinStorePackageLock") {
|
||||||
//A little hacky way to make yarn results
|
//A little hacky way to make yarn results
|
||||||
inputFile.fileValue(projectDir.resolve("yarnLockStub"))
|
inputFile.fileValue(projectDir.resolve("packageLockStub"))
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
|||||||
-4
@@ -5,15 +5,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.internal
|
package org.jetbrains.kotlin.gradle.internal
|
||||||
|
|
||||||
import jetbrains.buildServer.messages.serviceMessages.ServiceMessageParserCallback
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.api.internal.project.ProjectInternal
|
|
||||||
import org.gradle.internal.logging.progress.ProgressLogger
|
import org.gradle.internal.logging.progress.ProgressLogger
|
||||||
import org.gradle.internal.service.ServiceRegistry
|
import org.gradle.internal.service.ServiceRegistry
|
||||||
import org.gradle.process.ExecResult
|
import org.gradle.process.ExecResult
|
||||||
import org.gradle.process.internal.ExecAction
|
import org.gradle.process.internal.ExecAction
|
||||||
import org.gradle.process.internal.ExecActionFactory
|
import org.gradle.process.internal.ExecActionFactory
|
||||||
import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessageOutputStreamHandler
|
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.PipedInputStream
|
import java.io.PipedInputStream
|
||||||
import java.io.PipedOutputStream
|
import java.io.PipedOutputStream
|
||||||
|
|||||||
+5
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLI
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_INTERNAL_DIAGNOSTICS_USE_PARSABLE_FORMATTING
|
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_INTERNAL_DIAGNOSTICS_USE_PARSABLE_FORMATTING
|
||||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_JS_KARMA_BROWSERS
|
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_JS_KARMA_BROWSERS
|
||||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_JS_STDLIB_DOM_API_INCLUDED
|
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_JS_STDLIB_DOM_API_INCLUDED
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_JS_YARN
|
||||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ALLOW_LEGACY_DEPENDENCIES
|
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ALLOW_LEGACY_DEPENDENCIES
|
||||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ANDROID_GRADLE_PLUGIN_COMPATIBILITY_NO_WARN
|
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ANDROID_GRADLE_PLUGIN_COMPATIBILITY_NO_WARN
|
||||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ANDROID_SOURCE_SET_LAYOUT_ANDROID_STYLE_NO_WARN
|
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ANDROID_SOURCE_SET_LAYOUT_ANDROID_STYLE_NO_WARN
|
||||||
@@ -418,6 +419,9 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
|||||||
val stdlibDomApiIncluded: Boolean
|
val stdlibDomApiIncluded: Boolean
|
||||||
get() = booleanProperty(KOTLIN_JS_STDLIB_DOM_API_INCLUDED) ?: true
|
get() = booleanProperty(KOTLIN_JS_STDLIB_DOM_API_INCLUDED) ?: true
|
||||||
|
|
||||||
|
val yarn: Boolean
|
||||||
|
get() = booleanProperty(KOTLIN_JS_YARN) ?: true
|
||||||
|
|
||||||
val kotlinTestInferJvmVariant: Boolean
|
val kotlinTestInferJvmVariant: Boolean
|
||||||
get() = booleanProperty("kotlin.test.infer.jvm.variant") ?: true
|
get() = booleanProperty("kotlin.test.infer.jvm.variant") ?: true
|
||||||
|
|
||||||
@@ -613,6 +617,7 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
|||||||
val KOTLIN_STDLIB_DEFAULT_DEPENDENCY = property("kotlin.stdlib.default.dependency")
|
val KOTLIN_STDLIB_DEFAULT_DEPENDENCY = property("kotlin.stdlib.default.dependency")
|
||||||
val KOTLIN_STDLIB_JDK_VARIANTS_VERSION_ALIGNMENT = property("kotlin.stdlib.jdk.variants.version.alignment")
|
val KOTLIN_STDLIB_JDK_VARIANTS_VERSION_ALIGNMENT = property("kotlin.stdlib.jdk.variants.version.alignment")
|
||||||
val KOTLIN_JS_STDLIB_DOM_API_INCLUDED = property("kotlin.js.stdlib.dom.api.included")
|
val KOTLIN_JS_STDLIB_DOM_API_INCLUDED = property("kotlin.js.stdlib.dom.api.included")
|
||||||
|
val KOTLIN_JS_YARN = property("kotlin.js.yarn")
|
||||||
val KOTLIN_MPP_ENABLE_GRANULAR_SOURCE_SETS_METADATA = property("kotlin.mpp.enableGranularSourceSetsMetadata")
|
val KOTLIN_MPP_ENABLE_GRANULAR_SOURCE_SETS_METADATA = property("kotlin.mpp.enableGranularSourceSetsMetadata")
|
||||||
val KOTLIN_MPP_ENABLE_COMPATIBILITY_METADATA_VARIANT = property("kotlin.mpp.enableCompatibilityMetadataVariant")
|
val KOTLIN_MPP_ENABLE_COMPATIBILITY_METADATA_VARIANT = property("kotlin.mpp.enableCompatibilityMetadataVariant")
|
||||||
val KOTLIN_MPP_ENABLE_CINTEROP_COMMONIZATION = property("kotlin.mpp.enableCInteropCommonization")
|
val KOTLIN_MPP_ENABLE_CINTEROP_COMMONIZATION = property("kotlin.mpp.enableCInteropCommonization")
|
||||||
|
|||||||
+11
-4
@@ -138,9 +138,10 @@ abstract class AbstractSetupTask<Env : AbstractEnv, Settings : AbstractSettings<
|
|||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
file.useLines { seq ->
|
file.useLines { seq ->
|
||||||
val list = seq.first().split(" ")
|
val list = seq.first().split(" ")
|
||||||
list.size == 2 &&
|
list.size == 3 &&
|
||||||
list[0] == fileHasher.calculateDirHash(destination) &&
|
list[0] == CACHE_VERSION &&
|
||||||
list[1] == fileHasher.hash(dist).toByteArray().toHex().also { distHash = it }
|
list[1] == fileHasher.calculateDirHash(destination) &&
|
||||||
|
list[2] == fileHasher.hash(dist).toByteArray().toHex().also { distHash = it }
|
||||||
}
|
}
|
||||||
} else false
|
} else false
|
||||||
}
|
}
|
||||||
@@ -156,11 +157,17 @@ abstract class AbstractSetupTask<Env : AbstractEnv, Settings : AbstractSettings<
|
|||||||
extract(dist, destination.parentFile)
|
extract(dist, destination.parentFile)
|
||||||
|
|
||||||
destinationHashFile.writeText(
|
destinationHashFile.writeText(
|
||||||
fileHasher.calculateDirHash(destination)!! +
|
CACHE_VERSION +
|
||||||
|
" " +
|
||||||
|
fileHasher.calculateDirHash(destination)!! +
|
||||||
" " +
|
" " +
|
||||||
(distHash ?: fileHasher.hash(dist).toByteArray().toHex())
|
(distHash ?: fileHasher.hash(dist).toByteArray().toHex())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract fun extract(archive: File, destination: File)
|
abstract fun extract(archive: File, destination: File)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val CACHE_VERSION = "2"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -52,9 +52,9 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) :
|
|||||||
override fun configureTestDependencies(test: KotlinJsTest) {
|
override fun configureTestDependencies(test: KotlinJsTest) {
|
||||||
test.dependsOn(
|
test.dependsOn(
|
||||||
nodeJs.npmInstallTaskProvider,
|
nodeJs.npmInstallTaskProvider,
|
||||||
nodeJs.storeYarnLockTaskProvider,
|
|
||||||
nodeJs.nodeJsSetupTaskProvider
|
nodeJs.nodeJsSetupTaskProvider
|
||||||
)
|
)
|
||||||
|
test.dependsOn(nodeJs.packageManagerExtension.map { it.postInstallTasks })
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun configureDefaultTestFramework(test: KotlinJsTest) {
|
override fun configureDefaultTestFramework(test: KotlinJsTest) {
|
||||||
@@ -267,10 +267,11 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) :
|
|||||||
) {
|
) {
|
||||||
dependsOn(
|
dependsOn(
|
||||||
nodeJs.npmInstallTaskProvider,
|
nodeJs.npmInstallTaskProvider,
|
||||||
nodeJs.storeYarnLockTaskProvider,
|
|
||||||
target.project.tasks.named(compilation.processResourcesTaskName)
|
target.project.tasks.named(compilation.processResourcesTaskName)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
dependsOn(nodeJs.packageManagerExtension.map { it.postInstallTasks })
|
||||||
|
|
||||||
configureOptimization(mode)
|
configureOptimization(mode)
|
||||||
|
|
||||||
this.inputFilesDirectory.set(inputFilesDirectory)
|
this.inputFilesDirectory.set(inputFilesDirectory)
|
||||||
|
|||||||
+1
-1
@@ -62,8 +62,8 @@ abstract class KotlinNodeJsIr @Inject constructor(target: KotlinJsIrTarget) :
|
|||||||
if (target.wasmTargetType != KotlinWasmTargetType.WASI) {
|
if (target.wasmTargetType != KotlinWasmTargetType.WASI) {
|
||||||
test.dependsOn(
|
test.dependsOn(
|
||||||
nodeJsTaskProviders.npmInstallTaskProvider,
|
nodeJsTaskProviders.npmInstallTaskProvider,
|
||||||
nodeJsTaskProviders.storeYarnLockTaskProvider,
|
|
||||||
)
|
)
|
||||||
|
test.dependsOn(nodeJs.packageManagerExtension.map { it.postInstallTasks })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
package org.jetbrains.kotlin.gradle.targets.js.nodejs
|
package org.jetbrains.kotlin.gradle.targets.js.nodejs
|
||||||
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.AbstractEnv
|
import org.jetbrains.kotlin.gradle.targets.js.AbstractEnv
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmApi
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmApiExecution
|
||||||
import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore
|
import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ data class NodeJsEnv(
|
|||||||
override val ivyDependency: String,
|
override val ivyDependency: String,
|
||||||
override val downloadBaseUrl: String?,
|
override val downloadBaseUrl: String?,
|
||||||
|
|
||||||
val packageManager: NpmApi,
|
val packageManager: NpmApiExecution<PackageManagerEnvironment>,
|
||||||
) : AbstractEnv {
|
) : AbstractEnv {
|
||||||
val isWindows: Boolean
|
val isWindows: Boolean
|
||||||
get() = platformName == "win"
|
get() = platformName == "win"
|
||||||
|
|||||||
+1
-1
@@ -113,8 +113,8 @@ constructor(
|
|||||||
it.workingDir(npmProject.dir)
|
it.workingDir(npmProject.dir)
|
||||||
it.dependsOn(
|
it.dependsOn(
|
||||||
nodeJsTaskProviders.npmInstallTaskProvider,
|
nodeJsTaskProviders.npmInstallTaskProvider,
|
||||||
nodeJsTaskProviders.storeYarnLockTaskProvider,
|
|
||||||
)
|
)
|
||||||
|
it.dependsOn(nodeJs.packageManagerExtension.map { it.postInstallTasks })
|
||||||
}
|
}
|
||||||
it.dependsOn(nodeJsTaskProviders.nodeJsSetupTaskProvider)
|
it.dependsOn(nodeJsTaskProviders.nodeJsSetupTaskProvider)
|
||||||
it.dependsOn(compilation.compileKotlinTaskProvider)
|
it.dependsOn(compilation.compileKotlinTaskProvider)
|
||||||
|
|||||||
+14
-11
@@ -14,14 +14,14 @@ import org.jetbrains.kotlin.gradle.logging.kotlinInfo
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.AbstractSettings
|
import org.jetbrains.kotlin.gradle.targets.js.AbstractSettings
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.NpmVersions
|
import org.jetbrains.kotlin.gradle.targets.js.NpmVersions
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmApi
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinRootNpmResolver
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinRootNpmResolver
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.PACKAGE_JSON_UMBRELLA_TASK_NAME
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.PACKAGE_JSON_UMBRELLA_TASK_NAME
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmCachesSetup
|
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmCachesSetup
|
||||||
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.npm.tasks.RootPackageJsonTask
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.Yarn
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockCopyTask
|
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockCopyTask
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockStoreTask
|
||||||
|
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 org.jetbrains.kotlin.gradle.utils.getFile
|
import org.jetbrains.kotlin.gradle.utils.getFile
|
||||||
import org.jetbrains.kotlin.gradle.utils.property
|
import org.jetbrains.kotlin.gradle.utils.property
|
||||||
@@ -80,7 +80,7 @@ open class NodeJsRootExtension(
|
|||||||
// Release schedule: https://github.com/nodejs/Release
|
// Release schedule: https://github.com/nodejs/Release
|
||||||
// Actual LTS and Current versions: https://nodejs.org/en/download/
|
// Actual LTS and Current versions: https://nodejs.org/en/download/
|
||||||
// Older versions and more information, e.g. V8 version inside: https://nodejs.org/en/download/releases/
|
// Older versions and more information, e.g. V8 version inside: https://nodejs.org/en/download/releases/
|
||||||
override var version by Property("18.12.1")
|
override var version by Property("20.10.0")
|
||||||
|
|
||||||
override var command by Property("node")
|
override var command by Property("node")
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ open class NodeJsRootExtension(
|
|||||||
command = value
|
command = value
|
||||||
}
|
}
|
||||||
|
|
||||||
var packageManager: NpmApi by Property(Yarn())
|
val packageManagerExtension: org.gradle.api.provider.Property<NpmApiExt> = project.objects.property()
|
||||||
|
|
||||||
val taskRequirements: TasksRequirements
|
val taskRequirements: TasksRequirements
|
||||||
get() = resolver.tasksRequirements
|
get() = resolver.tasksRequirements
|
||||||
@@ -135,7 +135,7 @@ open class NodeJsRootExtension(
|
|||||||
val name = platform.get().name
|
val name = platform.get().name
|
||||||
val architecture = platform.get().arch
|
val architecture = platform.get().arch
|
||||||
|
|
||||||
val nodeDirName = "node-v$nodeVersion-$name-$architecture"
|
val nodeDirName = "node-v$version-$name-$architecture"
|
||||||
val cleanableStore = CleanableStore[installationDir.absolutePath]
|
val cleanableStore = CleanableStore[installationDir.absolutePath]
|
||||||
val nodeDir = cleanableStore[nodeDirName].use()
|
val nodeDir = cleanableStore[nodeDirName].use()
|
||||||
val isWindows = platform.get().isWindows()
|
val isWindows = platform.get().isWindows()
|
||||||
@@ -148,21 +148,23 @@ open class NodeJsRootExtension(
|
|||||||
|
|
||||||
fun getIvyDependency(): String {
|
fun getIvyDependency(): String {
|
||||||
val type = if (isWindows) "zip" else "tar.gz"
|
val type = if (isWindows) "zip" else "tar.gz"
|
||||||
return "org.nodejs:node:$nodeVersion:$name-$architecture@$type"
|
return "org.nodejs:node:$version:$name-$architecture@$type"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
packageManagerExtension.disallowChanges()
|
||||||
|
|
||||||
return NodeJsEnv(
|
return NodeJsEnv(
|
||||||
download = download,
|
download = download,
|
||||||
cleanableStore = cleanableStore,
|
cleanableStore = cleanableStore,
|
||||||
rootPackageDir = rootPackageDirectory.getFile(),
|
rootPackageDir = rootPackageDirectory.getFile(),
|
||||||
dir = nodeDir,
|
dir = nodeDir,
|
||||||
nodeBinDir = nodeBinDir,
|
nodeBinDir = nodeBinDir,
|
||||||
nodeExecutable = getExecutable("node", nodeCommand, "exe"),
|
nodeExecutable = getExecutable("node", command, "exe"),
|
||||||
platformName = name,
|
platformName = name,
|
||||||
architectureName = architecture,
|
architectureName = architecture,
|
||||||
ivyDependency = getIvyDependency(),
|
ivyDependency = getIvyDependency(),
|
||||||
downloadBaseUrl = nodeDownloadBaseUrl,
|
downloadBaseUrl = downloadBaseUrl,
|
||||||
packageManager = packageManager
|
packageManager = packageManagerExtension.get().packageManager
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,8 +183,9 @@ open class NodeJsRootExtension(
|
|||||||
val npmCachesSetupTaskProvider: TaskProvider<out KotlinNpmCachesSetup>
|
val npmCachesSetupTaskProvider: TaskProvider<out KotlinNpmCachesSetup>
|
||||||
get() = project.tasks.withType(KotlinNpmCachesSetup::class.java).named(KotlinNpmCachesSetup.NAME)
|
get() = project.tasks.withType(KotlinNpmCachesSetup::class.java).named(KotlinNpmCachesSetup.NAME)
|
||||||
|
|
||||||
val storeYarnLockTaskProvider: TaskProvider<out YarnLockCopyTask>
|
@Deprecated("This is deprecated and will be removed. Use corresponding property from YarnRootExtension")
|
||||||
get() = project.tasks.withType(YarnLockCopyTask::class.java).named(YarnLockCopyTask.STORE_YARN_LOCK_NAME)
|
val storeYarnLockTaskProvider: TaskProvider<YarnLockStoreTask>
|
||||||
|
get() = project.yarn.storeYarnLockTaskProvider
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val EXTENSION_NAME: String = "kotlinNodeJs"
|
const val EXTENSION_NAME: String = "kotlinNodeJs"
|
||||||
|
|||||||
+186
-35
@@ -8,24 +8,29 @@ package org.jetbrains.kotlin.gradle.targets.js.nodejs
|
|||||||
import org.gradle.api.Plugin
|
import org.gradle.api.Plugin
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.Task
|
import org.gradle.api.Task
|
||||||
|
import org.gradle.api.file.RegularFile
|
||||||
import org.gradle.api.plugins.BasePlugin
|
import org.gradle.api.plugins.BasePlugin
|
||||||
import org.gradle.api.provider.Provider
|
import org.gradle.api.provider.Provider
|
||||||
|
import org.gradle.api.tasks.TaskProvider
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
||||||
import org.jetbrains.kotlin.gradle.plugin.internal.configurationTimePropertiesAccessor
|
import org.jetbrains.kotlin.gradle.plugin.internal.configurationTimePropertiesAccessor
|
||||||
import org.jetbrains.kotlin.gradle.plugin.internal.usedAtConfigurationTime
|
import org.jetbrains.kotlin.gradle.plugin.internal.usedAtConfigurationTime
|
||||||
import org.jetbrains.kotlin.gradle.plugin.variantImplementationFactory
|
import org.jetbrains.kotlin.gradle.plugin.variantImplementationFactory
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.MultiplePluginDeclarationDetector
|
import org.jetbrains.kotlin.gradle.targets.js.MultiplePluginDeclarationDetector
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.GradleNodeModulesCache
|
import org.jetbrains.kotlin.gradle.targets.js.npm.*
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.KotlinNpmResolutionManager
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.UsesKotlinNpmResolutionManager
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinRootNpmResolver
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinRootNpmResolver
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.PACKAGE_JSON_UMBRELLA_TASK_NAME
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.PACKAGE_JSON_UMBRELLA_TASK_NAME
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.implementing
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmCachesSetup
|
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmCachesSetup
|
||||||
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.YarnPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin
|
||||||
import org.jetbrains.kotlin.gradle.tasks.CleanDataTask
|
import org.jetbrains.kotlin.gradle.tasks.CleanDataTask
|
||||||
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
||||||
import org.jetbrains.kotlin.gradle.tasks.withType
|
import org.jetbrains.kotlin.gradle.utils.castIsolatedKotlinPluginClassLoaderAware
|
||||||
import org.jetbrains.kotlin.gradle.utils.*
|
import org.jetbrains.kotlin.gradle.utils.getFile
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.onlyIfCompat
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.providerWithLazyConvention
|
||||||
|
|
||||||
open class NodeJsRootPlugin : Plugin<Project> {
|
open class NodeJsRootPlugin : Plugin<Project> {
|
||||||
override fun apply(project: Project) {
|
override fun apply(project: Project) {
|
||||||
@@ -43,8 +48,24 @@ open class NodeJsRootPlugin : Plugin<Project> {
|
|||||||
project
|
project
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val npm = project.extensions.create(
|
||||||
|
NpmExtension.EXTENSION_NAME,
|
||||||
|
NpmExtension::class.java,
|
||||||
|
project
|
||||||
|
)
|
||||||
|
|
||||||
addPlatform(project, nodeJs)
|
addPlatform(project, nodeJs)
|
||||||
|
|
||||||
|
npm.nodeJsEnvironment.value(
|
||||||
|
project.provider {
|
||||||
|
nodeJs.requireConfigured()
|
||||||
|
}
|
||||||
|
).disallowChanges()
|
||||||
|
|
||||||
|
nodeJs.packageManagerExtension.convention(
|
||||||
|
npm
|
||||||
|
)
|
||||||
|
|
||||||
val setupTask = project.registerTask<NodeJsSetupTask>(NodeJsSetupTask.NAME) {
|
val setupTask = project.registerTask<NodeJsSetupTask>(NodeJsSetupTask.NAME) {
|
||||||
it.group = TASKS_GROUP_NAME
|
it.group = TASKS_GROUP_NAME
|
||||||
it.description = "Download and install a local node/npm version"
|
it.description = "Download and install a local node/npm version"
|
||||||
@@ -97,21 +118,125 @@ open class NodeJsRootPlugin : Plugin<Project> {
|
|||||||
|
|
||||||
val objectFactory = project.objects
|
val objectFactory = project.objects
|
||||||
|
|
||||||
// TODO: Could we use common approach with build services to KotlinNpmResolutionManager?
|
val npmResolutionManager: Provider<KotlinNpmResolutionManager> = KotlinNpmResolutionManager.registerIfAbsent(
|
||||||
val npmResolutionManager = project.gradle.sharedServices.registerIfAbsent(
|
project,
|
||||||
KotlinNpmResolutionManager::class.java.name,
|
objectFactory.providerWithLazyConvention {
|
||||||
KotlinNpmResolutionManager::class.java
|
nodeJs.resolver.close()
|
||||||
) {
|
},
|
||||||
it.parameters.resolution.set(
|
gradleNodeModulesProvider,
|
||||||
objectFactory.providerWithLazyConvention {
|
nodeJs.projectPackagesDirectory
|
||||||
nodeJs.resolver.close()
|
)
|
||||||
}
|
|
||||||
)
|
val rootPackageJson = project.tasks.register(RootPackageJsonTask.NAME, RootPackageJsonTask::class.java) { task ->
|
||||||
it.parameters.gradleNodeModulesProvider.set(gradleNodeModulesProvider)
|
task.dependsOn(nodeJs.npmCachesSetupTaskProvider)
|
||||||
it.parameters.packagesDir.set(nodeJs.projectPackagesDirectory)
|
task.group = TASKS_GROUP_NAME
|
||||||
|
task.description = "Create root package.json"
|
||||||
|
|
||||||
|
task.npmResolutionManager.value(npmResolutionManager)
|
||||||
|
.disallowChanges()
|
||||||
|
|
||||||
|
task.onlyIfCompat("Prepare NPM project only in configuring state") {
|
||||||
|
it as RootPackageJsonTask
|
||||||
|
it.npmResolutionManager.get().isConfiguringState()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
YarnPlugin.apply(project)
|
configureRequiresNpmDependencies(project, rootPackageJson)
|
||||||
|
|
||||||
|
val packageJsonUmbrella = nodeJs
|
||||||
|
.packageJsonUmbrellaTaskProvider
|
||||||
|
|
||||||
|
nodeJs.rootPackageJsonTaskProvider.configure {
|
||||||
|
it.dependsOn(packageJsonUmbrella)
|
||||||
|
}
|
||||||
|
|
||||||
|
npmInstall.configure {
|
||||||
|
it.dependsOn(rootPackageJson)
|
||||||
|
it.inputs.property("npmIgnoreScripts", { npm.ignoreScripts })
|
||||||
|
}
|
||||||
|
|
||||||
|
project.tasks.register(LockCopyTask.STORE_PACKAGE_LOCK_NAME, LockStoreTask::class.java) { task ->
|
||||||
|
task.dependsOn(npmInstall)
|
||||||
|
task.inputFile.set(nodeJs.rootPackageDirectory.map { it.file(LockCopyTask.PACKAGE_LOCK) })
|
||||||
|
|
||||||
|
task.additionalInputFiles.from(
|
||||||
|
nodeJs.rootPackageDirectory.map { it.file(LockCopyTask.YARN_LOCK) }
|
||||||
|
)
|
||||||
|
task.additionalInputFiles.from(
|
||||||
|
task.outputDirectory.map { it.file(LockCopyTask.YARN_LOCK) }
|
||||||
|
)
|
||||||
|
|
||||||
|
task.outputDirectory.set(npm.lockFileDirectory)
|
||||||
|
task.fileName.set(npm.lockFileName)
|
||||||
|
|
||||||
|
task.lockFileMismatchReport.value(
|
||||||
|
project.provider { npm.requireConfigured().packageLockMismatchReport }
|
||||||
|
).disallowChanges()
|
||||||
|
task.reportNewLockFile.value(
|
||||||
|
project.provider { npm.requireConfigured().reportNewPackageLock }
|
||||||
|
).disallowChanges()
|
||||||
|
task.lockFileAutoReplace.value(
|
||||||
|
project.provider { npm.requireConfigured().packageLockAutoReplace }
|
||||||
|
).disallowChanges()
|
||||||
|
}
|
||||||
|
|
||||||
|
project.tasks.register(LockCopyTask.UPGRADE_PACKAGE_LOCK, LockStoreTask::class.java) { task ->
|
||||||
|
task.dependsOn(npmInstall)
|
||||||
|
task.inputFile.set(nodeJs.rootPackageDirectory.map { it.file(LockCopyTask.PACKAGE_LOCK) })
|
||||||
|
task.outputDirectory.set(npm.lockFileDirectory)
|
||||||
|
task.fileName.set(npm.lockFileName)
|
||||||
|
|
||||||
|
task.additionalInputFiles.from(
|
||||||
|
nodeJs.rootPackageDirectory.map { it.file(LockCopyTask.YARN_LOCK) }
|
||||||
|
)
|
||||||
|
task.additionalInputFiles.from(
|
||||||
|
task.outputDirectory.map { it.file(LockCopyTask.YARN_LOCK) }
|
||||||
|
)
|
||||||
|
|
||||||
|
task.lockFileMismatchReport.value(
|
||||||
|
LockFileMismatchReport.NONE
|
||||||
|
).disallowChanges()
|
||||||
|
task.reportNewLockFile.value(
|
||||||
|
false
|
||||||
|
).disallowChanges()
|
||||||
|
task.lockFileAutoReplace.value(
|
||||||
|
true
|
||||||
|
).disallowChanges()
|
||||||
|
}
|
||||||
|
|
||||||
|
project.tasks.register(LockCopyTask.RESTORE_PACKAGE_LOCK_NAME, LockCopyTask::class.java) { task ->
|
||||||
|
task.inputFile.set(
|
||||||
|
npm.lockFileDirectory.flatMap { dir ->
|
||||||
|
dir.file(npm.lockFileName)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
task.additionalInputFiles.from(
|
||||||
|
npm.lockFileDirectory.map { it.file(LockCopyTask.YARN_LOCK) }
|
||||||
|
)
|
||||||
|
task.outputDirectory.set(nodeJs.rootPackageDirectory)
|
||||||
|
task.fileName.set(LockCopyTask.PACKAGE_LOCK)
|
||||||
|
task.onlyIf {
|
||||||
|
val inputFileExists = task.inputFile.getOrNull()?.asFile?.exists() == true
|
||||||
|
// Workaround for "skip if not exists"
|
||||||
|
// https://github.com/gradle/gradle/issues/2919
|
||||||
|
if (!inputFileExists) {
|
||||||
|
task.inputFile.set(null as RegularFile?)
|
||||||
|
}
|
||||||
|
inputFileExists || task.additionalInputFiles.files.any { it.exists() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
npm.preInstallTasks.value(
|
||||||
|
listOf(npm.restorePackageLockTaskProvider)
|
||||||
|
).disallowChanges()
|
||||||
|
|
||||||
|
npm.postInstallTasks.value(
|
||||||
|
listOf(npm.storePackageLockTaskProvider)
|
||||||
|
).disallowChanges()
|
||||||
|
|
||||||
|
npmInstall.configure {
|
||||||
|
it.dependsOn(nodeJs.packageManagerExtension.map { it.preInstallTasks })
|
||||||
|
}
|
||||||
|
|
||||||
npmInstall.configure {
|
npmInstall.configure {
|
||||||
it.npmResolutionManager.value(npmResolutionManager).disallowChanges()
|
it.npmResolutionManager.value(npmResolutionManager).disallowChanges()
|
||||||
@@ -122,6 +247,12 @@ open class NodeJsRootPlugin : Plugin<Project> {
|
|||||||
it.group = TASKS_GROUP_NAME
|
it.group = TASKS_GROUP_NAME
|
||||||
it.description = "Clean unused local node version"
|
it.description = "Clean unused local node version"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val propertiesProvider = PropertiesProvider(project)
|
||||||
|
|
||||||
|
if (propertiesProvider.yarn) {
|
||||||
|
YarnPlugin.apply(project)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// from https://github.com/node-gradle/gradle-node-plugin
|
// from https://github.com/node-gradle/gradle-node-plugin
|
||||||
@@ -142,6 +273,42 @@ open class NodeJsRootPlugin : Plugin<Project> {
|
|||||||
).disallowChanges()
|
).disallowChanges()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Yes, we need to break Task Configuration Avoidance here
|
||||||
|
// In case when we need to create package.json's files and execute kotlinNpmInstall,
|
||||||
|
// We need to configure all RequiresNpmDependencies tasks to install them,
|
||||||
|
// Because we need to persist lock file
|
||||||
|
// We execute this block in configure phase of rootPackageJson to be sure,
|
||||||
|
// That Task Configuration Avoidance will not be broken for tasks not related with NPM installing
|
||||||
|
// https://youtrack.jetbrains.com/issue/KT-48241
|
||||||
|
private fun configureRequiresNpmDependencies(
|
||||||
|
project: Project,
|
||||||
|
rootPackageJson: TaskProvider<RootPackageJsonTask>,
|
||||||
|
) {
|
||||||
|
val fn: (Project) -> Unit = {
|
||||||
|
it.tasks.implementing(RequiresNpmDependencies::class)
|
||||||
|
.forEach {}
|
||||||
|
}
|
||||||
|
rootPackageJson.configure {
|
||||||
|
project.allprojects
|
||||||
|
.forEach { project ->
|
||||||
|
if (it.state.executed) {
|
||||||
|
fn(project)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project.allprojects
|
||||||
|
.forEach {
|
||||||
|
if (!it.state.executed) {
|
||||||
|
it.afterEvaluate { project ->
|
||||||
|
rootPackageJson.configure {
|
||||||
|
fn(project)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TASKS_GROUP_NAME: String = "nodeJs"
|
const val TASKS_GROUP_NAME: String = "nodeJs"
|
||||||
|
|
||||||
@@ -154,30 +321,14 @@ open class NodeJsRootPlugin : Plugin<Project> {
|
|||||||
val Project.kotlinNodeJsExtension: NodeJsRootExtension
|
val Project.kotlinNodeJsExtension: NodeJsRootExtension
|
||||||
get() = extensions.getByName(NodeJsRootExtension.EXTENSION_NAME).castIsolatedKotlinPluginClassLoaderAware()
|
get() = extensions.getByName(NodeJsRootExtension.EXTENSION_NAME).castIsolatedKotlinPluginClassLoaderAware()
|
||||||
|
|
||||||
private val Project.gradleNodeModules
|
|
||||||
get() = GradleNodeModulesCache.registerIfAbsent(
|
|
||||||
this,
|
|
||||||
null,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
|
|
||||||
val Project.kotlinNpmResolutionManager: Provider<KotlinNpmResolutionManager>
|
val Project.kotlinNpmResolutionManager: Provider<KotlinNpmResolutionManager>
|
||||||
get() {
|
get() {
|
||||||
val npmResolutionManager = project.gradle.sharedServices.registerIfAbsent(
|
return project.gradle.sharedServices.registerIfAbsent(
|
||||||
KotlinNpmResolutionManager::class.java.name,
|
KotlinNpmResolutionManager::class.java.name,
|
||||||
KotlinNpmResolutionManager::class.java
|
KotlinNpmResolutionManager::class.java
|
||||||
) {
|
) {
|
||||||
error("Must be already registered")
|
error("Must be already registered")
|
||||||
}
|
}
|
||||||
|
|
||||||
SingleActionPerProject.run(project, UsesKotlinNpmResolutionManager::class.java.name) {
|
|
||||||
project.tasks.withType<UsesKotlinNpmResolutionManager>().configureEach { task ->
|
|
||||||
task.usesService(npmResolutionManager)
|
|
||||||
task.usesService(gradleNodeModules)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return npmResolutionManager
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -43,7 +43,7 @@ abstract class NodeJsSetupTask : AbstractSetupTask<NodeJsEnv, NodeJsRootExtensio
|
|||||||
it.into(destination)
|
it.into(destination)
|
||||||
}
|
}
|
||||||
|
|
||||||
fixBrokenSymlinks(destination, env.isWindows, fixBrokenSymLinks)
|
fixBrokenSymlinks(this.destination, env.isWindows, fixBrokenSymLinks)
|
||||||
|
|
||||||
if (!env.isWindows) {
|
if (!env.isWindows) {
|
||||||
File(env.nodeExecutable).setExecutable(true)
|
File(env.nodeExecutable).setExecutable(true)
|
||||||
|
|||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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.nodejs
|
||||||
|
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.gradle.api.provider.ListProperty
|
||||||
|
import org.gradle.api.tasks.TaskProvider
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmApiExecution
|
||||||
|
|
||||||
|
interface NpmApiExtension<out Env : PackageManagerEnvironment, out NpmApi : NpmApiExecution<Env>> {
|
||||||
|
val packageManager: NpmApi
|
||||||
|
|
||||||
|
val environment: Env
|
||||||
|
|
||||||
|
val additionalInstallOutput: FileCollection
|
||||||
|
|
||||||
|
val preInstallTasks: ListProperty<TaskProvider<*>>
|
||||||
|
|
||||||
|
val postInstallTasks: ListProperty<TaskProvider<*>>
|
||||||
|
}
|
||||||
|
|
||||||
|
typealias NpmApiExt = NpmApiExtension<PackageManagerEnvironment, NpmApiExecution<PackageManagerEnvironment>>
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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.nodejs
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
interface PackageManagerEnvironment : Serializable
|
||||||
+1
-1
@@ -77,7 +77,7 @@ internal class GradleNodeModuleBuilder(
|
|||||||
|
|
||||||
packageJson.devDependencies.clear()
|
packageJson.devDependencies.clear()
|
||||||
|
|
||||||
// yarn requires semver
|
// npm requires semver
|
||||||
packageJson.version = fixSemver(packageJson.version)
|
packageJson.version = fixSemver(packageJson.version)
|
||||||
|
|
||||||
return makeNodeModule(cacheDir, packageJson) { nodeModule ->
|
return makeNodeModule(cacheDir, packageJson) { nodeModule ->
|
||||||
|
|||||||
+66
-11
@@ -5,20 +5,27 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.targets.js.npm
|
package org.jetbrains.kotlin.gradle.targets.js.npm
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.Task
|
import org.gradle.api.Task
|
||||||
import org.gradle.api.file.Directory
|
import org.gradle.api.file.Directory
|
||||||
import org.gradle.api.file.DirectoryProperty
|
import org.gradle.api.file.DirectoryProperty
|
||||||
import org.gradle.api.logging.Logger
|
import org.gradle.api.logging.Logger
|
||||||
import org.gradle.api.provider.Property
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
import org.gradle.api.services.BuildService
|
import org.gradle.api.services.BuildService
|
||||||
import org.gradle.api.services.BuildServiceParameters
|
import org.gradle.api.services.BuildServiceParameters
|
||||||
import org.gradle.api.tasks.Internal
|
import org.gradle.api.tasks.Internal
|
||||||
import org.gradle.internal.service.ServiceRegistry
|
import org.gradle.internal.service.ServiceRegistry
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.PackageManagerEnvironment
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.Installation
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.Installation
|
||||||
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.targets.js.npm.resolver.KotlinCompilationNpmResolver
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinCompilationNpmResolver
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinProjectNpmResolver
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinProjectNpmResolver
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinRootNpmResolver
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinRootNpmResolver
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.withType
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.SingleActionPerProject
|
||||||
|
import kotlin.contracts.ExperimentalContracts
|
||||||
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
internal interface UsesKotlinNpmResolutionManager : Task {
|
internal interface UsesKotlinNpmResolutionManager : Task {
|
||||||
@get:Internal
|
@get:Internal
|
||||||
@@ -78,16 +85,16 @@ abstract class KotlinNpmResolutionManager : BuildService<KotlinNpmResolutionMana
|
|||||||
|
|
||||||
internal fun prepare(
|
internal fun prepare(
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
npmEnvironment: NpmEnvironment,
|
nodeJsEnvironment: NodeJsEnvironment,
|
||||||
yarnEnvironment: YarnEnvironment,
|
environment: PackageManagerEnvironment,
|
||||||
) = prepareIfNeeded(logger = logger, npmEnvironment, yarnEnvironment)
|
) = prepareIfNeeded(logger = logger, nodeJsEnvironment, environment)
|
||||||
|
|
||||||
internal fun installIfNeeded(
|
internal fun installIfNeeded(
|
||||||
args: List<String> = emptyList(),
|
args: List<String> = emptyList(),
|
||||||
services: ServiceRegistry,
|
services: ServiceRegistry,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
npmEnvironment: NpmEnvironment,
|
nodeJsEnvironment: NodeJsEnvironment,
|
||||||
yarnEnvironment: YarnEnvironment,
|
packageManagerEnvironment: PackageManagerEnvironment,
|
||||||
): Unit? {
|
): Unit? {
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
if (state is ResolutionState.Installed) {
|
if (state is ResolutionState.Installed) {
|
||||||
@@ -99,8 +106,8 @@ abstract class KotlinNpmResolutionManager : BuildService<KotlinNpmResolutionMana
|
|||||||
}
|
}
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
val installation: Installation = prepareIfNeeded(logger = logger, npmEnvironment, yarnEnvironment)
|
val installation: Installation = prepareIfNeeded(logger = logger, nodeJsEnvironment, packageManagerEnvironment)
|
||||||
installation.install(args, services, logger, npmEnvironment, yarnEnvironment)
|
installation.install(args, services, logger, nodeJsEnvironment, packageManagerEnvironment)
|
||||||
state = ResolutionState.Installed()
|
state = ResolutionState.Installed()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
state = ResolutionState.Error(e)
|
state = ResolutionState.Error(e)
|
||||||
@@ -111,8 +118,8 @@ abstract class KotlinNpmResolutionManager : BuildService<KotlinNpmResolutionMana
|
|||||||
|
|
||||||
private fun prepareIfNeeded(
|
private fun prepareIfNeeded(
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
npmEnvironment: NpmEnvironment,
|
nodeJsEnvironment: NodeJsEnvironment,
|
||||||
yarnEnvironment: YarnEnvironment,
|
packageManagerEnvironment: PackageManagerEnvironment,
|
||||||
): Installation {
|
): Installation {
|
||||||
val state0 = this.state
|
val state0 = this.state
|
||||||
return when (state0) {
|
return when (state0) {
|
||||||
@@ -128,8 +135,8 @@ abstract class KotlinNpmResolutionManager : BuildService<KotlinNpmResolutionMana
|
|||||||
is ResolutionState.Configuring -> {
|
is ResolutionState.Configuring -> {
|
||||||
state1.resolution.prepareInstallation(
|
state1.resolution.prepareInstallation(
|
||||||
logger,
|
logger,
|
||||||
npmEnvironment,
|
nodeJsEnvironment,
|
||||||
yarnEnvironment,
|
packageManagerEnvironment,
|
||||||
this
|
this
|
||||||
).also {
|
).also {
|
||||||
this.state = ResolutionState.Prepared(it)
|
this.state = ResolutionState.Prepared(it)
|
||||||
@@ -146,4 +153,52 @@ abstract class KotlinNpmResolutionManager : BuildService<KotlinNpmResolutionMana
|
|||||||
is ResolutionState.Error -> throw state0.wrappedException
|
is ResolutionState.Error -> throw state0.wrappedException
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val serviceClass = KotlinNpmResolutionManager::class.java
|
||||||
|
private val serviceName = serviceClass.name
|
||||||
|
|
||||||
|
private fun registerIfAbsentImpl(
|
||||||
|
project: Project,
|
||||||
|
resolution: Provider<KotlinRootNpmResolution>?,
|
||||||
|
gradleNodeModulesProvider: Provider<GradleNodeModulesCache>?,
|
||||||
|
packagesDir: Provider<Directory>
|
||||||
|
): Provider<KotlinNpmResolutionManager> {
|
||||||
|
project.gradle.sharedServices.registrations.findByName(serviceName)?.let {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return it.service as Provider<KotlinNpmResolutionManager>
|
||||||
|
}
|
||||||
|
|
||||||
|
val message = {
|
||||||
|
"Build service KotlinNpmResolutionManager should be already registered"
|
||||||
|
}
|
||||||
|
|
||||||
|
requireNotNull(resolution, message)
|
||||||
|
requireNotNull(gradleNodeModulesProvider, message)
|
||||||
|
|
||||||
|
return project.gradle.sharedServices.registerIfAbsent(serviceName, serviceClass) {
|
||||||
|
it.parameters.resolution.set(
|
||||||
|
resolution
|
||||||
|
)
|
||||||
|
it.parameters.gradleNodeModulesProvider.set(gradleNodeModulesProvider)
|
||||||
|
it.parameters.packagesDir.set(packagesDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun registerIfAbsent(
|
||||||
|
project: Project,
|
||||||
|
resolution: Provider<KotlinRootNpmResolution>?,
|
||||||
|
gradleNodeModulesProvider: Provider<GradleNodeModulesCache>?,
|
||||||
|
packagesDir: Provider<Directory>
|
||||||
|
) = registerIfAbsentImpl(project, resolution, gradleNodeModulesProvider, packagesDir).also { serviceProvider ->
|
||||||
|
SingleActionPerProject.run(project, UsesKotlinNpmResolutionManager::class.java.name) {
|
||||||
|
project.tasks.withType<UsesKotlinNpmResolutionManager>().configureEach { task ->
|
||||||
|
task.usesService(serviceProvider)
|
||||||
|
if (gradleNodeModulesProvider != null) {
|
||||||
|
task.usesService(gradleNodeModulesProvider)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+76
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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.DefaultTask
|
||||||
|
import org.gradle.api.file.*
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
|
import org.gradle.api.tasks.*
|
||||||
|
import org.gradle.work.DisableCachingByDefault
|
||||||
|
import org.gradle.work.NormalizeLineEndings
|
||||||
|
import java.io.File
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@DisableCachingByDefault
|
||||||
|
abstract class LockCopyTask : DefaultTask() {
|
||||||
|
|
||||||
|
@get:NormalizeLineEndings
|
||||||
|
@get:InputFile
|
||||||
|
@get:Optional
|
||||||
|
@get:PathSensitive(PathSensitivity.RELATIVE)
|
||||||
|
abstract val inputFile: RegularFileProperty
|
||||||
|
|
||||||
|
@get:NormalizeLineEndings
|
||||||
|
@get:InputFiles
|
||||||
|
@get:PathSensitive(PathSensitivity.RELATIVE)
|
||||||
|
val additionalInputFiles: ConfigurableFileCollection = project.objects.fileCollection()
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
abstract val outputDirectory: DirectoryProperty
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
abstract val fileName: Property<String>
|
||||||
|
|
||||||
|
@get:OutputFile
|
||||||
|
val outputFile: Provider<File>
|
||||||
|
get() = outputDirectory.map { dir ->
|
||||||
|
dir.asFile.resolve(fileName.get())
|
||||||
|
}
|
||||||
|
|
||||||
|
@get:Inject
|
||||||
|
abstract val fs: FileSystemOperations
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
open fun copy() {
|
||||||
|
fs.copy { copy ->
|
||||||
|
inputFile.getOrNull()?.let { inputFile ->
|
||||||
|
copy.from(inputFile) {
|
||||||
|
it.rename { fileName.get() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
copy.from(additionalInputFiles)
|
||||||
|
copy.into(outputDirectory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val STORE_PACKAGE_LOCK_NAME = "kotlinStorePackageLock"
|
||||||
|
const val RESTORE_PACKAGE_LOCK_NAME = "kotlinRestorePackageLock"
|
||||||
|
const val UPGRADE_PACKAGE_LOCK = "kotlinUpgradePackageLock"
|
||||||
|
const val PACKAGE_LOCK_MISMATCH_MESSAGE = "Lock file was changed. Run the `$UPGRADE_PACKAGE_LOCK` task to actualize lock file"
|
||||||
|
const val KOTLIN_JS_STORE = "kotlin-js-store"
|
||||||
|
const val PACKAGE_LOCK = "package-lock.json"
|
||||||
|
const val YARN_LOCK = "yarn.lock"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class LockFileMismatchReport {
|
||||||
|
NONE,
|
||||||
|
WARNING,
|
||||||
|
FAIL,
|
||||||
|
}
|
||||||
+59
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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.GradleException
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.tasks.Input
|
||||||
|
import org.gradle.work.DisableCachingByDefault
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.contentEquals
|
||||||
|
|
||||||
|
@DisableCachingByDefault
|
||||||
|
abstract class LockStoreTask : LockCopyTask() {
|
||||||
|
@get:Input
|
||||||
|
abstract val lockFileMismatchReport: Property<LockFileMismatchReport>
|
||||||
|
|
||||||
|
@get:Input
|
||||||
|
abstract val reportNewLockFile: Property<Boolean>
|
||||||
|
|
||||||
|
@get:Input
|
||||||
|
abstract val lockFileAutoReplace: Property<Boolean>
|
||||||
|
|
||||||
|
override fun copy() {
|
||||||
|
val outputFile = outputDirectory.get().asFile.resolve(fileName.get())
|
||||||
|
|
||||||
|
val value = inputFile.orNull
|
||||||
|
requireNotNull(value) {
|
||||||
|
"Input file $fileName should exist"
|
||||||
|
}
|
||||||
|
|
||||||
|
val shouldReportMismatch = if (!outputFile.exists()) {
|
||||||
|
reportNewLockFile.get()
|
||||||
|
} else {
|
||||||
|
lockFileMismatchReport.get() != LockFileMismatchReport.NONE && !contentEquals(value.asFile, outputFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
// outputFile is updated only with auto replace or not existed, but we need delete all other files initially
|
||||||
|
fs.delete {
|
||||||
|
it.delete(additionalInputFiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!outputFile.exists() || lockFileAutoReplace.get()) {
|
||||||
|
super.copy()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldReportMismatch) {
|
||||||
|
when (lockFileMismatchReport.get()) {
|
||||||
|
LockFileMismatchReport.NONE -> {}
|
||||||
|
LockFileMismatchReport.WARNING -> {
|
||||||
|
logger.warn(PACKAGE_LOCK_MISMATCH_MESSAGE)
|
||||||
|
}
|
||||||
|
LockFileMismatchReport.FAIL -> throw GradleException(PACKAGE_LOCK_MISMATCH_MESSAGE)
|
||||||
|
else -> error("Unknown mismatch report kind")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+139
@@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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.logging.Logger
|
||||||
|
import org.gradle.internal.service.ServiceRegistry
|
||||||
|
import org.jetbrains.kotlin.gradle.internal.execWithProgress
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.PreparedKotlinCompilationNpmResolution
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.getFile
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class Npm : NpmApiExecution<NpmEnvironment> {
|
||||||
|
|
||||||
|
override fun preparedFiles(nodeJs: NodeJsEnvironment): Collection<File> {
|
||||||
|
return listOf(
|
||||||
|
nodeJs
|
||||||
|
.rootPackageDir
|
||||||
|
.resolve(NpmProject.PACKAGE_JSON)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun prepareRootProject(
|
||||||
|
nodeJs: NodeJsEnvironment,
|
||||||
|
packageManagerEnvironment: NpmEnvironment,
|
||||||
|
rootProjectName: String,
|
||||||
|
rootProjectVersion: String,
|
||||||
|
subProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
|
) {
|
||||||
|
return prepareRootPackageJson(
|
||||||
|
nodeJs,
|
||||||
|
rootProjectName,
|
||||||
|
rootProjectVersion,
|
||||||
|
subProjects,
|
||||||
|
packageManagerEnvironment.overrides
|
||||||
|
.associate { it.path to it.toVersionString() },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun prepareRootPackageJson(
|
||||||
|
nodeJs: NodeJsEnvironment,
|
||||||
|
rootProjectName: String,
|
||||||
|
rootProjectVersion: String,
|
||||||
|
npmProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
|
overrides: Map<String, String>,
|
||||||
|
) {
|
||||||
|
val rootPackageJsonFile = preparedFiles(nodeJs).single()
|
||||||
|
|
||||||
|
saveRootProjectWorkspacesPackageJson(
|
||||||
|
rootProjectName,
|
||||||
|
rootProjectVersion,
|
||||||
|
npmProjects,
|
||||||
|
overrides,
|
||||||
|
rootPackageJsonFile
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resolveRootProject(
|
||||||
|
services: ServiceRegistry,
|
||||||
|
logger: Logger,
|
||||||
|
nodeJs: NodeJsEnvironment,
|
||||||
|
packageManagerEnvironment: NpmEnvironment,
|
||||||
|
npmProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
|
cliArgs: List<String>,
|
||||||
|
) {
|
||||||
|
val nodeJsWorldDir = nodeJs.rootPackageDir
|
||||||
|
|
||||||
|
npmExec(
|
||||||
|
services,
|
||||||
|
logger,
|
||||||
|
nodeJs,
|
||||||
|
packageManagerEnvironment,
|
||||||
|
nodeJsWorldDir,
|
||||||
|
NpmApiExecution.resolveOperationDescription("npm"),
|
||||||
|
cliArgs
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun npmExec(
|
||||||
|
services: ServiceRegistry,
|
||||||
|
logger: Logger,
|
||||||
|
nodeJs: NodeJsEnvironment,
|
||||||
|
environment: NpmEnvironment,
|
||||||
|
dir: File,
|
||||||
|
description: String,
|
||||||
|
args: List<String>,
|
||||||
|
) {
|
||||||
|
services.execWithProgress(description) { exec ->
|
||||||
|
val arguments = listOf("install") + args
|
||||||
|
.plus(
|
||||||
|
if (logger.isDebugEnabled) "--verbose" else ""
|
||||||
|
)
|
||||||
|
.plus(
|
||||||
|
if (environment.ignoreScripts) "--ignore-scripts" else ""
|
||||||
|
).filter { it.isNotEmpty() }
|
||||||
|
|
||||||
|
if (!environment.standalone) {
|
||||||
|
val nodeExecutable = nodeJs.nodeExecutable
|
||||||
|
val nodePath = File(nodeExecutable).parent
|
||||||
|
exec.environment(
|
||||||
|
"PATH",
|
||||||
|
"$nodePath${File.pathSeparator}${System.getenv("PATH")}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val command = environment.executable
|
||||||
|
|
||||||
|
exec.executable = command
|
||||||
|
exec.args = arguments
|
||||||
|
|
||||||
|
exec.workingDir = dir
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveRootProjectWorkspacesPackageJson(
|
||||||
|
rootProjectName: String,
|
||||||
|
rootProjectVersion: String,
|
||||||
|
npmProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
|
overrides: Map<String, String>,
|
||||||
|
rootPackageJsonFile: File,
|
||||||
|
) {
|
||||||
|
val nodeJsWorldDir = rootPackageJsonFile.parentFile
|
||||||
|
val rootPackageJson = PackageJson(rootProjectName, rootProjectVersion)
|
||||||
|
rootPackageJson.private = true
|
||||||
|
|
||||||
|
val npmProjectWorkspaces = npmProjects.map { it.npmProjectDir.getFile().relativeTo(nodeJsWorldDir).path }
|
||||||
|
val importedProjectWorkspaces =
|
||||||
|
NpmImportedPackagesVersionResolver(npmProjects, nodeJsWorldDir).resolveAndUpdatePackages()
|
||||||
|
|
||||||
|
rootPackageJson.workspaces = npmProjectWorkspaces + importedProjectWorkspaces
|
||||||
|
rootPackageJson.overrides = overrides
|
||||||
|
rootPackageJson.saveTo(
|
||||||
|
rootPackageJsonFile
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
-30
@@ -8,32 +8,30 @@ package org.jetbrains.kotlin.gradle.targets.js.npm
|
|||||||
import org.gradle.api.logging.Logger
|
import org.gradle.api.logging.Logger
|
||||||
import org.gradle.internal.service.ServiceRegistry
|
import org.gradle.internal.service.ServiceRegistry
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsEnv
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsEnv
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.PackageManagerEnvironment
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.PreparedKotlinCompilationNpmResolution
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.PreparedKotlinCompilationNpmResolution
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnEnv
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnResolution
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NodeJS package manager API
|
* NodeJS package manager API
|
||||||
*/
|
*/
|
||||||
interface NpmApi : Serializable {
|
interface NpmApiExecution<out T : PackageManagerEnvironment> : Serializable {
|
||||||
fun preparedFiles(nodeJs: NpmEnvironment): Collection<File>
|
fun preparedFiles(nodeJs: NodeJsEnvironment): Collection<File>
|
||||||
|
|
||||||
fun prepareRootProject(
|
fun prepareRootProject(
|
||||||
nodeJs: NpmEnvironment,
|
nodeJs: NodeJsEnvironment,
|
||||||
|
packageManagerEnvironment: @UnsafeVariance T,
|
||||||
rootProjectName: String,
|
rootProjectName: String,
|
||||||
rootProjectVersion: String,
|
rootProjectVersion: String,
|
||||||
logger: Logger,
|
|
||||||
subProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
subProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
resolutions: Map<String, String>,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
fun resolveRootProject(
|
fun resolveRootProject(
|
||||||
services: ServiceRegistry,
|
services: ServiceRegistry,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
nodeJs: NpmEnvironment,
|
nodeJs: NodeJsEnvironment,
|
||||||
yarn: YarnEnvironment,
|
packageManagerEnvironment: @UnsafeVariance T,
|
||||||
npmProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
npmProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
cliArgs: List<String>
|
cliArgs: List<String>
|
||||||
)
|
)
|
||||||
@@ -44,32 +42,15 @@ interface NpmApi : Serializable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class NpmEnvironment(
|
data class NodeJsEnvironment(
|
||||||
val rootPackageDir: File,
|
val rootPackageDir: File,
|
||||||
val nodeExecutable: String,
|
val nodeExecutable: String,
|
||||||
val isWindows: Boolean,
|
val packageManager: NpmApiExecution<PackageManagerEnvironment>
|
||||||
val packageManager: NpmApi
|
|
||||||
) : Serializable
|
) : Serializable
|
||||||
|
|
||||||
internal val NodeJsEnv.asNpmEnvironment
|
internal val NodeJsEnv.asNodeJsEnvironment
|
||||||
get() = NpmEnvironment(
|
get() = NodeJsEnvironment(
|
||||||
rootPackageDir,
|
rootPackageDir,
|
||||||
nodeExecutable,
|
nodeExecutable,
|
||||||
isWindows,
|
|
||||||
packageManager
|
packageManager
|
||||||
)
|
|
||||||
|
|
||||||
data class YarnEnvironment(
|
|
||||||
val executable: String,
|
|
||||||
val standalone: Boolean,
|
|
||||||
val ignoreScripts: Boolean,
|
|
||||||
val yarnResolutions: List<YarnResolution>
|
|
||||||
) : Serializable
|
|
||||||
|
|
||||||
internal val YarnEnv.asYarnEnvironment
|
|
||||||
get() = YarnEnvironment(
|
|
||||||
executable,
|
|
||||||
standalone,
|
|
||||||
ignoreScripts,
|
|
||||||
yarnResolutions
|
|
||||||
)
|
)
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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
|
||||||
|
|
||||||
|
data class NpmEnv(
|
||||||
|
val executable: String,
|
||||||
|
val ignoreScripts: Boolean,
|
||||||
|
val standalone: Boolean,
|
||||||
|
val packageLockMismatchReport: LockFileMismatchReport,
|
||||||
|
val reportNewPackageLock: Boolean,
|
||||||
|
val packageLockAutoReplace: Boolean,
|
||||||
|
val overrides: List<NpmOverride>
|
||||||
|
)
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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.jetbrains.kotlin.gradle.targets.js.nodejs.PackageManagerEnvironment
|
||||||
|
|
||||||
|
data class NpmEnvironment(
|
||||||
|
val executable: String,
|
||||||
|
val ignoreScripts: Boolean,
|
||||||
|
val standalone: Boolean,
|
||||||
|
val overrides: List<NpmOverride>
|
||||||
|
) : PackageManagerEnvironment
|
||||||
|
|
||||||
|
internal val NpmEnv.asNpmEnvironment
|
||||||
|
get() = NpmEnvironment(
|
||||||
|
executable,
|
||||||
|
ignoreScripts,
|
||||||
|
standalone,
|
||||||
|
overrides
|
||||||
|
)
|
||||||
+126
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.Action
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.Task
|
||||||
|
import org.gradle.api.file.DirectoryProperty
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.gradle.api.provider.ListProperty
|
||||||
|
import org.gradle.api.tasks.TaskProvider
|
||||||
|
import org.jetbrains.kotlin.gradle.internal.ConfigurationPhaseAware
|
||||||
|
import org.jetbrains.kotlin.gradle.logging.kotlinInfo
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsEnv
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NpmApiExtension
|
||||||
|
|
||||||
|
open class NpmExtension(
|
||||||
|
val project: Project,
|
||||||
|
) : ConfigurationPhaseAware<NpmEnv>(), NpmApiExtension<NpmEnvironment, Npm> {
|
||||||
|
init {
|
||||||
|
check(project == project.rootProject)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val gradleHome = project.gradle.gradleUserHomeDir.also {
|
||||||
|
project.logger.kotlinInfo("Storing cached files in $it")
|
||||||
|
}
|
||||||
|
|
||||||
|
override val packageManager: Npm by lazy {
|
||||||
|
Npm()
|
||||||
|
}
|
||||||
|
|
||||||
|
override val environment: NpmEnvironment by lazy {
|
||||||
|
requireConfigured().asNpmEnvironment
|
||||||
|
}
|
||||||
|
|
||||||
|
override val additionalInstallOutput: FileCollection = project.objects.fileCollection().from(
|
||||||
|
{
|
||||||
|
nodeJsEnvironment.get().rootPackageDir.resolve("package-lock.json")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
override val preInstallTasks: ListProperty<TaskProvider<*>> = project.objects.listProperty(TaskProvider::class.java)
|
||||||
|
|
||||||
|
override val postInstallTasks: ListProperty<TaskProvider<*>> = project.objects.listProperty(TaskProvider::class.java)
|
||||||
|
|
||||||
|
val command: org.gradle.api.provider.Property<String> = project.objects.property(String::class.java)
|
||||||
|
.convention("npm")
|
||||||
|
|
||||||
|
val lockFileName: org.gradle.api.provider.Property<String> = project.objects.property(String::class.java)
|
||||||
|
.convention(LockCopyTask.PACKAGE_LOCK)
|
||||||
|
val lockFileDirectory: DirectoryProperty = project.objects.directoryProperty()
|
||||||
|
.convention(project.layout.projectDirectory.dir(LockCopyTask.KOTLIN_JS_STORE))
|
||||||
|
|
||||||
|
val ignoreScripts: org.gradle.api.provider.Property<Boolean> = project.objects.property(Boolean::class.java)
|
||||||
|
.convention(true)
|
||||||
|
|
||||||
|
val packageLockMismatchReport: org.gradle.api.provider.Property<LockFileMismatchReport> =
|
||||||
|
project.objects.property(LockFileMismatchReport::class.java)
|
||||||
|
.convention(LockFileMismatchReport.FAIL)
|
||||||
|
|
||||||
|
val reportNewPackageLock: org.gradle.api.provider.Property<Boolean> = project.objects.property(Boolean::class.java)
|
||||||
|
.convention(false)
|
||||||
|
|
||||||
|
val packageLockAutoReplace: org.gradle.api.provider.Property<Boolean> = project.objects.property(Boolean::class.java)
|
||||||
|
.convention(false)
|
||||||
|
|
||||||
|
val overrides: ListProperty<NpmOverride> = project.objects.listProperty(NpmOverride::class.java)
|
||||||
|
|
||||||
|
fun override(path: String, configure: Action<NpmOverride>) {
|
||||||
|
overrides.add(
|
||||||
|
NpmOverride(path)
|
||||||
|
.apply { configure.execute(this) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun override(path: String, version: String) {
|
||||||
|
override(path, Action {
|
||||||
|
it.include(version)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val nodeJsEnvironment: org.gradle.api.provider.Property<NodeJsEnv> = project.objects.property(NodeJsEnv::class.java)
|
||||||
|
|
||||||
|
override fun finalizeConfiguration(): NpmEnv {
|
||||||
|
val nodeJsEnvironmentValue = nodeJsEnvironment.get()
|
||||||
|
val isWindows = nodeJsEnvironmentValue.isWindows
|
||||||
|
|
||||||
|
fun getExecutable(command: String, customCommand: String, windowsExtension: String): String {
|
||||||
|
val finalCommand = if (isWindows && customCommand == command) "$command.$windowsExtension" else customCommand
|
||||||
|
return if (nodeJsEnvironmentValue.download)
|
||||||
|
nodeJsEnvironmentValue.nodeBinDir
|
||||||
|
.resolve(finalCommand).absolutePath
|
||||||
|
else
|
||||||
|
finalCommand
|
||||||
|
}
|
||||||
|
return NpmEnv(
|
||||||
|
executable = getExecutable("npm", command.get(), "cmd"),
|
||||||
|
ignoreScripts = ignoreScripts.get(),
|
||||||
|
standalone = !nodeJsEnvironmentValue.download,
|
||||||
|
packageLockMismatchReport = packageLockMismatchReport.get(),
|
||||||
|
reportNewPackageLock = reportNewPackageLock.get(),
|
||||||
|
packageLockAutoReplace = packageLockAutoReplace.get(),
|
||||||
|
overrides = overrides.get()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val restorePackageLockTaskProvider: TaskProvider<out Task>
|
||||||
|
get() = project.tasks.named(LockCopyTask.RESTORE_PACKAGE_LOCK_NAME)
|
||||||
|
|
||||||
|
val storePackageLockTaskProvider: TaskProvider<out Task>
|
||||||
|
get() = project.tasks.named(LockCopyTask.STORE_PACKAGE_LOCK_NAME)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val EXTENSION_NAME: String = "kotlinNpm"
|
||||||
|
|
||||||
|
operator fun get(project: Project): NpmExtension {
|
||||||
|
val rootProject = project.rootProject
|
||||||
|
rootProject.plugins.apply(NodeJsRootPlugin::class.java)
|
||||||
|
return rootProject.extensions.getByName(EXTENSION_NAME) as NpmExtension
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-6
@@ -1,17 +1,14 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2023 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.
|
* 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.yarn
|
package org.jetbrains.kotlin.gradle.targets.js.npm
|
||||||
|
|
||||||
import org.gradle.api.logging.Logger
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.GradleNodeModule
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.PreparedKotlinCompilationNpmResolution
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.PreparedKotlinCompilationNpmResolution
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class YarnImportedPackagesVersionResolver(
|
class NpmImportedPackagesVersionResolver(
|
||||||
private val logger: Logger,
|
|
||||||
npmProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
npmProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
private val nodeJsWorldDir: File
|
private val nodeJsWorldDir: File
|
||||||
) {
|
) {
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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 java.io.Serializable
|
||||||
|
|
||||||
|
class NpmOverride(
|
||||||
|
val path: String
|
||||||
|
) : Serializable {
|
||||||
|
var includedVersions = mutableListOf<String>()
|
||||||
|
var excludedVersions = mutableListOf<String>()
|
||||||
|
|
||||||
|
fun include(vararg include: String) {
|
||||||
|
includedVersions.addAll(include)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exclude(vararg exclude: String) {
|
||||||
|
excludedVersions.addAll(exclude)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun NpmOverride.toVersionString(): String {
|
||||||
|
return buildNpmVersion(includedVersions, excludedVersions)
|
||||||
|
}
|
||||||
+2
-1
@@ -30,8 +30,9 @@ class NpmResolverPlugin : Plugin<Project> {
|
|||||||
}
|
}
|
||||||
task.dependsOn(
|
task.dependsOn(
|
||||||
kotlinNodeJsTaskProvidersExtension.npmInstallTaskProvider,
|
kotlinNodeJsTaskProvidersExtension.npmInstallTaskProvider,
|
||||||
kotlinNodeJsTaskProvidersExtension.storeYarnLockTaskProvider,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
task.dependsOn(nodeJs.packageManagerExtension.map { it.postInstallTasks })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ class PackageJson(
|
|||||||
|
|
||||||
var workspaces: Collection<String>? = null
|
var workspaces: Collection<String>? = null
|
||||||
|
|
||||||
var resolutions: Map<String, String>? = null
|
var overrides: Map<String, String>? = null
|
||||||
|
|
||||||
var types: String? = null
|
var types: String? = null
|
||||||
|
|
||||||
|
|||||||
+12
-15
@@ -7,10 +7,9 @@ package org.jetbrains.kotlin.gradle.targets.js.npm.resolved
|
|||||||
|
|
||||||
import org.gradle.api.logging.Logger
|
import org.gradle.api.logging.Logger
|
||||||
import org.gradle.internal.service.ServiceRegistry
|
import org.gradle.internal.service.ServiceRegistry
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.PackageManagerEnvironment
|
||||||
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.NpmEnvironment
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NodeJsEnvironment
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.YarnEnvironment
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.toVersionString
|
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
class KotlinRootNpmResolution(
|
class KotlinRootNpmResolution(
|
||||||
@@ -25,8 +24,8 @@ class KotlinRootNpmResolution(
|
|||||||
*/
|
*/
|
||||||
internal fun prepareInstallation(
|
internal fun prepareInstallation(
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
npmEnvironment: NpmEnvironment,
|
nodeJsEnvironment: NodeJsEnvironment,
|
||||||
yarnEnvironment: YarnEnvironment,
|
packageManagerEnvironment: PackageManagerEnvironment,
|
||||||
npmResolutionManager: KotlinNpmResolutionManager,
|
npmResolutionManager: KotlinNpmResolutionManager,
|
||||||
): Installation {
|
): Installation {
|
||||||
synchronized(projects) {
|
synchronized(projects) {
|
||||||
@@ -41,14 +40,12 @@ class KotlinRootNpmResolution(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
npmEnvironment.packageManager.prepareRootProject(
|
nodeJsEnvironment.packageManager.prepareRootProject(
|
||||||
npmEnvironment,
|
nodeJsEnvironment,
|
||||||
|
packageManagerEnvironment,
|
||||||
rootProjectName,
|
rootProjectName,
|
||||||
rootProjectVersion,
|
rootProjectVersion,
|
||||||
logger,
|
|
||||||
projectResolutions,
|
projectResolutions,
|
||||||
yarnEnvironment.yarnResolutions
|
|
||||||
.associate { it.path to it.toVersionString() },
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return Installation(
|
return Installation(
|
||||||
@@ -63,15 +60,15 @@ class Installation(val compilationResolutions: Collection<PreparedKotlinCompilat
|
|||||||
args: List<String>,
|
args: List<String>,
|
||||||
services: ServiceRegistry,
|
services: ServiceRegistry,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
npmEnvironment: NpmEnvironment,
|
nodeJsEnvironment: NodeJsEnvironment,
|
||||||
yarnEnvironment: YarnEnvironment,
|
packageManagerEnvironment: PackageManagerEnvironment,
|
||||||
) {
|
) {
|
||||||
synchronized(compilationResolutions) {
|
synchronized(compilationResolutions) {
|
||||||
npmEnvironment.packageManager.resolveRootProject(
|
nodeJsEnvironment.packageManager.resolveRootProject(
|
||||||
services,
|
services,
|
||||||
logger,
|
logger,
|
||||||
npmEnvironment,
|
nodeJsEnvironment,
|
||||||
yarnEnvironment,
|
packageManagerEnvironment,
|
||||||
compilationResolutions,
|
compilationResolutions,
|
||||||
args
|
args
|
||||||
)
|
)
|
||||||
|
|||||||
+21
-24
@@ -10,14 +10,7 @@ import org.gradle.api.file.Directory
|
|||||||
import org.gradle.api.file.FileCollection
|
import org.gradle.api.file.FileCollection
|
||||||
import org.gradle.api.file.RegularFile
|
import org.gradle.api.file.RegularFile
|
||||||
import org.gradle.api.provider.Provider
|
import org.gradle.api.provider.Provider
|
||||||
import org.gradle.api.tasks.IgnoreEmptyDirectories
|
import org.gradle.api.tasks.*
|
||||||
import org.gradle.api.tasks.Input
|
|
||||||
import org.gradle.api.tasks.InputFiles
|
|
||||||
import org.gradle.api.tasks.Internal
|
|
||||||
import org.gradle.api.tasks.OutputFile
|
|
||||||
import org.gradle.api.tasks.PathSensitive
|
|
||||||
import org.gradle.api.tasks.PathSensitivity
|
|
||||||
import org.gradle.api.tasks.TaskAction
|
|
||||||
import org.gradle.work.DisableCachingByDefault
|
import org.gradle.work.DisableCachingByDefault
|
||||||
import org.gradle.work.NormalizeLineEndings
|
import org.gradle.work.NormalizeLineEndings
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
|
||||||
@@ -25,10 +18,8 @@ import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.
|
|||||||
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.NpmProject
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.UsesKotlinNpmResolutionManager
|
import org.jetbrains.kotlin.gradle.targets.js.npm.UsesKotlinNpmResolutionManager
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.asNpmEnvironment
|
import org.jetbrains.kotlin.gradle.targets.js.npm.asNodeJsEnvironment
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.asYarnEnvironment
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinRootNpmResolver
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinRootNpmResolver
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.yarn
|
|
||||||
import org.jetbrains.kotlin.gradle.utils.getFile
|
import org.jetbrains.kotlin.gradle.utils.getFile
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -46,9 +37,6 @@ abstract class KotlinNpmInstallTask :
|
|||||||
private val nodeJs: NodeJsRootExtension
|
private val nodeJs: NodeJsRootExtension
|
||||||
get() = project.rootProject.kotlinNodeJsExtension
|
get() = project.rootProject.kotlinNodeJsExtension
|
||||||
|
|
||||||
private val yarn
|
|
||||||
get() = project.rootProject.yarn
|
|
||||||
|
|
||||||
private val rootResolver: KotlinRootNpmResolver
|
private val rootResolver: KotlinRootNpmResolver
|
||||||
get() = nodeJs.resolver
|
get() = nodeJs.resolver
|
||||||
|
|
||||||
@@ -57,12 +45,12 @@ abstract class KotlinNpmInstallTask :
|
|||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
private val npmEnvironment by lazy {
|
private val nodsJsEnvironment by lazy {
|
||||||
nodeJs.requireConfigured().asNpmEnvironment
|
nodeJs.requireConfigured().asNodeJsEnvironment
|
||||||
}
|
}
|
||||||
|
|
||||||
private val yarnEnv by lazy {
|
private val packageManagerEnv by lazy {
|
||||||
yarn.requireConfigured().asYarnEnvironment
|
nodeJs.packageManagerExtension.get().environment
|
||||||
}
|
}
|
||||||
|
|
||||||
@Input
|
@Input
|
||||||
@@ -73,7 +61,7 @@ abstract class KotlinNpmInstallTask :
|
|||||||
@get:NormalizeLineEndings
|
@get:NormalizeLineEndings
|
||||||
@get:InputFiles
|
@get:InputFiles
|
||||||
val preparedFiles: Collection<File> by lazy {
|
val preparedFiles: Collection<File> by lazy {
|
||||||
nodeJs.packageManager.preparedFiles(npmEnvironment)
|
nodeJs.packageManagerExtension.get().packageManager.preparedFiles(nodsJsEnvironment)
|
||||||
}
|
}
|
||||||
|
|
||||||
@get:PathSensitive(PathSensitivity.RELATIVE)
|
@get:PathSensitive(PathSensitivity.RELATIVE)
|
||||||
@@ -92,12 +80,21 @@ abstract class KotlinNpmInstallTask :
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@get:OutputFile
|
@get:OutputFiles
|
||||||
|
val additionalFiles: FileCollection by lazy {
|
||||||
|
nodeJs.packageManagerExtension.get().additionalInstallOutput
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated(
|
||||||
|
"This property is deprecated and will be removed in future. Use additionalFiles instead",
|
||||||
|
replaceWith = ReplaceWith("additionalFiles")
|
||||||
|
)
|
||||||
|
@get:Internal
|
||||||
val yarnLockFile: Provider<RegularFile> = nodeJs.rootPackageDirectory.map { it.file("yarn.lock") }
|
val yarnLockFile: Provider<RegularFile> = nodeJs.rootPackageDirectory.map { it.file("yarn.lock") }
|
||||||
|
|
||||||
@Deprecated(
|
@Deprecated(
|
||||||
"This property is deprecated and will be removed in future. Use yarnLockFile instead",
|
"This property is deprecated and will be removed in future. Use additionalFiles instead",
|
||||||
replaceWith = ReplaceWith("yarnLockFile")
|
replaceWith = ReplaceWith("additionalFiles")
|
||||||
)
|
)
|
||||||
@get:Internal
|
@get:Internal
|
||||||
val yarnLock: File
|
val yarnLock: File
|
||||||
@@ -115,8 +112,8 @@ abstract class KotlinNpmInstallTask :
|
|||||||
args = args,
|
args = args,
|
||||||
services = services,
|
services = services,
|
||||||
logger = logger,
|
logger = logger,
|
||||||
npmEnvironment,
|
nodsJsEnvironment,
|
||||||
yarnEnv
|
packageManagerEnv
|
||||||
) ?: throw (npmResolutionManager.get().state as KotlinNpmResolutionManager.ResolutionState.Error).wrappedException
|
) ?: throw (npmResolutionManager.get().state as KotlinNpmResolutionManager.ResolutionState.Error).wrappedException
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-11
@@ -16,10 +16,8 @@ import org.gradle.work.NormalizeLineEndings
|
|||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension
|
||||||
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.UsesKotlinNpmResolutionManager
|
import org.jetbrains.kotlin.gradle.targets.js.npm.UsesKotlinNpmResolutionManager
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.asNpmEnvironment
|
import org.jetbrains.kotlin.gradle.targets.js.npm.asNodeJsEnvironment
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.asYarnEnvironment
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinRootNpmResolver
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinRootNpmResolver
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.yarn
|
|
||||||
import org.jetbrains.kotlin.gradle.utils.getFile
|
import org.jetbrains.kotlin.gradle.utils.getFile
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -37,9 +35,6 @@ abstract class RootPackageJsonTask :
|
|||||||
private val nodeJs
|
private val nodeJs
|
||||||
get() = project.rootProject.kotlinNodeJsExtension
|
get() = project.rootProject.kotlinNodeJsExtension
|
||||||
|
|
||||||
private val yarn
|
|
||||||
get() = project.rootProject.yarn
|
|
||||||
|
|
||||||
private val rootResolver: KotlinRootNpmResolver
|
private val rootResolver: KotlinRootNpmResolver
|
||||||
get() = nodeJs.resolver
|
get() = nodeJs.resolver
|
||||||
|
|
||||||
@@ -48,12 +43,12 @@ abstract class RootPackageJsonTask :
|
|||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
private val npmEnvironment by lazy {
|
private val nodeJsEnvironment by lazy {
|
||||||
nodeJs.requireConfigured().asNpmEnvironment
|
nodeJs.requireConfigured().asNodeJsEnvironment
|
||||||
}
|
}
|
||||||
|
|
||||||
private val yarnEnv by lazy {
|
private val packageManagerEnv by lazy {
|
||||||
yarn.requireConfigured().asYarnEnvironment
|
nodeJs.packageManagerExtension.get().environment
|
||||||
}
|
}
|
||||||
|
|
||||||
@get:OutputFile
|
@get:OutputFile
|
||||||
@@ -87,7 +82,7 @@ abstract class RootPackageJsonTask :
|
|||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
fun resolve() {
|
fun resolve() {
|
||||||
npmResolutionManager.get().prepare(logger, npmEnvironment, yarnEnv)
|
npmResolutionManager.get().prepare(logger, nodeJsEnvironment, packageManagerEnv)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
+1
-1
@@ -46,7 +46,7 @@ fun FileHasher.calculateDirHash(
|
|||||||
dir.walk()
|
dir.walk()
|
||||||
.forEach { file ->
|
.forEach { file ->
|
||||||
hasher.putString(file.toRelativeString(dir))
|
hasher.putString(file.toRelativeString(dir))
|
||||||
if (file.isFile && !Files.isSymbolicLink(file.toPath())) {
|
if (file.isFile) {
|
||||||
if (!Files.isSymbolicLink(file.toPath())) {
|
if (!Files.isSymbolicLink(file.toPath())) {
|
||||||
hasher.putHash(hash(file))
|
hasher.putHash(hash(file))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* 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.yarn
|
||||||
|
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
|
import org.gradle.api.tasks.Internal
|
||||||
|
import org.gradle.work.DisableCachingByDefault
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.LockCopyTask
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.LockFileMismatchReport
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.LockStoreTask
|
||||||
|
|
||||||
|
@DisableCachingByDefault
|
||||||
|
abstract class YarnLockCopyTask : LockCopyTask()
|
||||||
|
|
||||||
|
@DisableCachingByDefault
|
||||||
|
abstract class YarnLockStoreTask : LockStoreTask() {
|
||||||
|
@Internal
|
||||||
|
val yarnLockMismatchReport: Provider<YarnLockMismatchReport> = lockFileMismatchReport.map { it.fromLockFileMismatchReport() }
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
val reportNewYarnLock: Provider<Boolean> = reportNewLockFile
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
val yarnLockAutoReplace: Provider<Boolean> = lockFileAutoReplace
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class YarnLockMismatchReport {
|
||||||
|
NONE,
|
||||||
|
WARNING,
|
||||||
|
FAIL;
|
||||||
|
|
||||||
|
fun toLockFileMismatchReport(): LockFileMismatchReport =
|
||||||
|
when(this) {
|
||||||
|
NONE -> LockFileMismatchReport.NONE
|
||||||
|
WARNING -> LockFileMismatchReport.WARNING
|
||||||
|
FAIL -> LockFileMismatchReport.FAIL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun LockFileMismatchReport.fromLockFileMismatchReport(): YarnLockMismatchReport =
|
||||||
|
when(this) {
|
||||||
|
LockFileMismatchReport.NONE -> YarnLockMismatchReport.NONE
|
||||||
|
LockFileMismatchReport.WARNING -> YarnLockMismatchReport.WARNING
|
||||||
|
LockFileMismatchReport.FAIL -> YarnLockMismatchReport.FAIL
|
||||||
|
}
|
||||||
+8
-11
@@ -7,39 +7,36 @@ package org.jetbrains.kotlin.gradle.targets.js.yarn
|
|||||||
|
|
||||||
import org.gradle.api.logging.Logger
|
import org.gradle.api.logging.Logger
|
||||||
import org.gradle.internal.service.ServiceRegistry
|
import org.gradle.internal.service.ServiceRegistry
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmApi
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmApiExecution
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmEnvironment
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NodeJsEnvironment
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.YarnEnvironment
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.PreparedKotlinCompilationNpmResolution
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.PreparedKotlinCompilationNpmResolution
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class Yarn : NpmApi {
|
class Yarn : NpmApiExecution<YarnEnvironment> {
|
||||||
private val yarnWorkspaces = YarnWorkspaces()
|
private val yarnWorkspaces = YarnWorkspaces()
|
||||||
|
|
||||||
override fun preparedFiles(nodeJs: NpmEnvironment): Collection<File> =
|
override fun preparedFiles(nodeJs: NodeJsEnvironment): Collection<File> =
|
||||||
yarnWorkspaces.preparedFiles(nodeJs)
|
yarnWorkspaces.preparedFiles(nodeJs)
|
||||||
|
|
||||||
override fun prepareRootProject(
|
override fun prepareRootProject(
|
||||||
nodeJs: NpmEnvironment,
|
nodeJs: NodeJsEnvironment,
|
||||||
|
yarn: YarnEnvironment,
|
||||||
rootProjectName: String,
|
rootProjectName: String,
|
||||||
rootProjectVersion: String,
|
rootProjectVersion: String,
|
||||||
logger: Logger,
|
|
||||||
subProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
subProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
resolutions: Map<String, String>,
|
|
||||||
) = yarnWorkspaces
|
) = yarnWorkspaces
|
||||||
.prepareRootProject(
|
.prepareRootProject(
|
||||||
nodeJs,
|
nodeJs,
|
||||||
|
yarn,
|
||||||
rootProjectName,
|
rootProjectName,
|
||||||
rootProjectVersion,
|
rootProjectVersion,
|
||||||
logger,
|
|
||||||
subProjects,
|
subProjects,
|
||||||
resolutions,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun resolveRootProject(
|
override fun resolveRootProject(
|
||||||
services: ServiceRegistry,
|
services: ServiceRegistry,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
nodeJs: NpmEnvironment,
|
nodeJs: NodeJsEnvironment,
|
||||||
yarn: YarnEnvironment,
|
yarn: YarnEnvironment,
|
||||||
npmProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
npmProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
cliArgs: List<String>
|
cliArgs: List<String>
|
||||||
|
|||||||
+5
-10
@@ -8,17 +8,16 @@ package org.jetbrains.kotlin.gradle.targets.js.yarn
|
|||||||
import org.gradle.api.logging.Logger
|
import org.gradle.api.logging.Logger
|
||||||
import org.gradle.internal.service.ServiceRegistry
|
import org.gradle.internal.service.ServiceRegistry
|
||||||
import org.jetbrains.kotlin.gradle.internal.execWithProgress
|
import org.jetbrains.kotlin.gradle.internal.execWithProgress
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmApi
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmApiExecution
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmEnvironment
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NodeJsEnvironment
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.YarnEnvironment
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
abstract class YarnBasics : NpmApi {
|
abstract class YarnBasics : NpmApiExecution<YarnEnvironment> {
|
||||||
|
|
||||||
fun yarnExec(
|
fun yarnExec(
|
||||||
services: ServiceRegistry,
|
services: ServiceRegistry,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
nodeJs: NpmEnvironment,
|
nodeJs: NodeJsEnvironment,
|
||||||
yarn: YarnEnvironment,
|
yarn: YarnEnvironment,
|
||||||
dir: File,
|
dir: File,
|
||||||
description: String,
|
description: String,
|
||||||
@@ -35,11 +34,7 @@ abstract class YarnBasics : NpmApi {
|
|||||||
|
|
||||||
val nodeExecutable = nodeJs.nodeExecutable
|
val nodeExecutable = nodeJs.nodeExecutable
|
||||||
if (!yarn.ignoreScripts) {
|
if (!yarn.ignoreScripts) {
|
||||||
val nodePath = if (nodeJs.isWindows) {
|
val nodePath = File(nodeExecutable).parent
|
||||||
File(nodeExecutable).parent
|
|
||||||
} else {
|
|
||||||
nodeExecutable
|
|
||||||
}
|
|
||||||
exec.environment(
|
exec.environment(
|
||||||
"PATH",
|
"PATH",
|
||||||
"$nodePath${File.pathSeparator}${System.getenv("PATH")}"
|
"$nodePath${File.pathSeparator}${System.getenv("PATH")}"
|
||||||
|
|||||||
-17
@@ -1,17 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2020 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.yarn
|
|
||||||
|
|
||||||
import org.gradle.api.GradleException
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.FILE_VERSION_PREFIX
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.includedRange
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.intersect
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
private const val SEPARATOR = "@"
|
|
||||||
|
|
||||||
private const val FILE_MARKER = "${SEPARATOR}$FILE_VERSION_PREFIX"
|
|
||||||
private const val GITHUB_MARKER = "${SEPARATOR}github:"
|
|
||||||
+4
-2
@@ -16,10 +16,12 @@ data class YarnEnv(
|
|||||||
override val dir: File,
|
override val dir: File,
|
||||||
val executable: String,
|
val executable: String,
|
||||||
override val ivyDependency: String,
|
override val ivyDependency: String,
|
||||||
val standalone: Boolean,
|
|
||||||
val ignoreScripts: Boolean,
|
val ignoreScripts: Boolean,
|
||||||
val yarnLockMismatchReport: YarnLockMismatchReport,
|
val yarnLockMismatchReport: YarnLockMismatchReport,
|
||||||
val reportNewYarnLock: Boolean,
|
val reportNewYarnLock: Boolean,
|
||||||
val yarnLockAutoReplace: Boolean,
|
val yarnLockAutoReplace: Boolean,
|
||||||
val yarnResolutions: List<YarnResolution>
|
val yarnResolutions: List<YarnResolution>
|
||||||
) : AbstractEnv
|
) : AbstractEnv {
|
||||||
|
val standalone: Boolean
|
||||||
|
get() = !download
|
||||||
|
}
|
||||||
|
|||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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.yarn
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.PackageManagerEnvironment
|
||||||
|
|
||||||
|
data class YarnEnvironment(
|
||||||
|
val executable: String,
|
||||||
|
val standalone: Boolean,
|
||||||
|
val ignoreScripts: Boolean,
|
||||||
|
val yarnResolutions: List<YarnResolution>
|
||||||
|
) : PackageManagerEnvironment
|
||||||
|
|
||||||
|
internal val YarnEnv.asYarnEnvironment
|
||||||
|
get() = YarnEnvironment(
|
||||||
|
executable,
|
||||||
|
standalone,
|
||||||
|
ignoreScripts,
|
||||||
|
yarnResolutions
|
||||||
|
)
|
||||||
-103
@@ -1,103 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.yarn
|
|
||||||
|
|
||||||
import org.gradle.api.DefaultTask
|
|
||||||
import org.gradle.api.GradleException
|
|
||||||
import org.gradle.api.file.DirectoryProperty
|
|
||||||
import org.gradle.api.file.FileSystemOperations
|
|
||||||
import org.gradle.api.file.RegularFileProperty
|
|
||||||
import org.gradle.api.provider.Property
|
|
||||||
import org.gradle.api.provider.Provider
|
|
||||||
import org.gradle.api.tasks.*
|
|
||||||
import org.gradle.work.DisableCachingByDefault
|
|
||||||
import org.gradle.work.NormalizeLineEndings
|
|
||||||
import org.jetbrains.kotlin.gradle.utils.contentEquals
|
|
||||||
import java.io.File
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
@DisableCachingByDefault
|
|
||||||
abstract class YarnLockCopyTask : DefaultTask() {
|
|
||||||
|
|
||||||
@get:NormalizeLineEndings
|
|
||||||
@get:InputFile
|
|
||||||
@get:PathSensitive(PathSensitivity.RELATIVE)
|
|
||||||
abstract val inputFile: RegularFileProperty
|
|
||||||
|
|
||||||
@get:Internal
|
|
||||||
abstract val outputDirectory: DirectoryProperty
|
|
||||||
|
|
||||||
@get:Internal
|
|
||||||
abstract val fileName: Property<String>
|
|
||||||
|
|
||||||
@get:OutputFile
|
|
||||||
val outputFile: Provider<File>
|
|
||||||
get() = outputDirectory.map { regularFile ->
|
|
||||||
regularFile.asFile.resolve(fileName.get())
|
|
||||||
}
|
|
||||||
|
|
||||||
@get:Inject
|
|
||||||
abstract val fs: FileSystemOperations
|
|
||||||
|
|
||||||
@TaskAction
|
|
||||||
open fun copy() {
|
|
||||||
fs.copy { copy ->
|
|
||||||
copy.from(inputFile)
|
|
||||||
copy.rename { fileName.get() }
|
|
||||||
copy.into(outputDirectory)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val STORE_YARN_LOCK_NAME = "kotlinStoreYarnLock"
|
|
||||||
val RESTORE_YARN_LOCK_NAME = "kotlinRestoreYarnLock"
|
|
||||||
val UPGRADE_YARN_LOCK = "kotlinUpgradeYarnLock"
|
|
||||||
val YARN_LOCK_MISMATCH_MESSAGE = "yarn.lock was changed. Run the `${YarnLockCopyTask.UPGRADE_YARN_LOCK}` task to actualize yarn.lock file"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@DisableCachingByDefault
|
|
||||||
abstract class YarnLockStoreTask : YarnLockCopyTask() {
|
|
||||||
@Input
|
|
||||||
lateinit var yarnLockMismatchReport: Provider<YarnLockMismatchReport>
|
|
||||||
|
|
||||||
@Input
|
|
||||||
lateinit var reportNewYarnLock: Provider<Boolean>
|
|
||||||
|
|
||||||
@Input
|
|
||||||
lateinit var yarnLockAutoReplace: Provider<Boolean>
|
|
||||||
|
|
||||||
override fun copy() {
|
|
||||||
val outputFile = outputDirectory.get().asFile.resolve(fileName.get())
|
|
||||||
|
|
||||||
val shouldReportMismatch = if (!outputFile.exists()) {
|
|
||||||
reportNewYarnLock.get()
|
|
||||||
} else {
|
|
||||||
yarnLockMismatchReport.get() != YarnLockMismatchReport.NONE && !contentEquals(inputFile.get().asFile, outputFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!outputFile.exists() || yarnLockAutoReplace.get()) {
|
|
||||||
super.copy()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldReportMismatch) {
|
|
||||||
when (yarnLockMismatchReport.get()) {
|
|
||||||
YarnLockMismatchReport.NONE -> {}
|
|
||||||
YarnLockMismatchReport.WARNING -> {
|
|
||||||
logger.warn(YARN_LOCK_MISMATCH_MESSAGE)
|
|
||||||
}
|
|
||||||
YarnLockMismatchReport.FAIL -> throw GradleException(YARN_LOCK_MISMATCH_MESSAGE)
|
|
||||||
else -> error("Unknown yarn.lock mismatch report kind")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class YarnLockMismatchReport {
|
|
||||||
NONE,
|
|
||||||
WARNING,
|
|
||||||
FAIL,
|
|
||||||
}
|
|
||||||
+35
-81
@@ -7,22 +7,14 @@ package org.jetbrains.kotlin.gradle.targets.js.yarn
|
|||||||
|
|
||||||
import org.gradle.api.Plugin
|
import org.gradle.api.Plugin
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.tasks.TaskProvider
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.MultiplePluginDeclarationDetector
|
import org.jetbrains.kotlin.gradle.targets.js.MultiplePluginDeclarationDetector
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNpmResolutionManager
|
import org.jetbrains.kotlin.gradle.targets.js.npm.LockCopyTask
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.implementing
|
|
||||||
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.YarnLockCopyTask.Companion.RESTORE_YARN_LOCK_NAME
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockCopyTask.Companion.STORE_YARN_LOCK_NAME
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockCopyTask.Companion.UPGRADE_YARN_LOCK
|
|
||||||
import org.jetbrains.kotlin.gradle.tasks.CleanDataTask
|
import org.jetbrains.kotlin.gradle.tasks.CleanDataTask
|
||||||
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
||||||
import org.jetbrains.kotlin.gradle.utils.detachedResolvable
|
import org.jetbrains.kotlin.gradle.utils.detachedResolvable
|
||||||
import org.jetbrains.kotlin.gradle.utils.onlyIfCompat
|
|
||||||
|
|
||||||
open class YarnPlugin : Plugin<Project> {
|
open class YarnPlugin : Plugin<Project> {
|
||||||
override fun apply(project: Project): Unit = project.run {
|
override fun apply(project: Project): Unit = project.run {
|
||||||
@@ -40,6 +32,10 @@ open class YarnPlugin : Plugin<Project> {
|
|||||||
yarnRootExtension.platform.value(nodeJs.platform)
|
yarnRootExtension.platform.value(nodeJs.platform)
|
||||||
.disallowChanges()
|
.disallowChanges()
|
||||||
|
|
||||||
|
nodeJs.packageManagerExtension.set(
|
||||||
|
yarnRootExtension
|
||||||
|
)
|
||||||
|
|
||||||
val setupTask = registerTask<YarnSetupTask>(YarnSetupTask.NAME) {
|
val setupTask = registerTask<YarnSetupTask>(YarnSetupTask.NAME) {
|
||||||
it.dependsOn(nodeJsTaskProviders.nodeJsSetupTaskProvider)
|
it.dependsOn(nodeJsTaskProviders.nodeJsSetupTaskProvider)
|
||||||
|
|
||||||
@@ -52,110 +48,64 @@ open class YarnPlugin : Plugin<Project> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val kotlinNpmResolutionManager = project.kotlinNpmResolutionManager
|
|
||||||
|
|
||||||
val rootPackageJson = tasks.register(RootPackageJsonTask.NAME, RootPackageJsonTask::class.java) { task ->
|
|
||||||
task.dependsOn(nodeJsTaskProviders.npmCachesSetupTaskProvider)
|
|
||||||
task.group = NodeJsRootPlugin.TASKS_GROUP_NAME
|
|
||||||
task.description = "Create root package.json"
|
|
||||||
|
|
||||||
task.npmResolutionManager.value(kotlinNpmResolutionManager)
|
|
||||||
.disallowChanges()
|
|
||||||
|
|
||||||
task.onlyIfCompat("Prepare NPM project only in configuring state") {
|
|
||||||
it as RootPackageJsonTask
|
|
||||||
it.npmResolutionManager.get().isConfiguringState()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configureRequiresNpmDependencies(project, rootPackageJson)
|
|
||||||
|
|
||||||
val kotlinNpmInstall = tasks.named(KotlinNpmInstallTask.NAME)
|
val kotlinNpmInstall = tasks.named(KotlinNpmInstallTask.NAME)
|
||||||
kotlinNpmInstall.configure {
|
kotlinNpmInstall.configure {
|
||||||
it.dependsOn(rootPackageJson)
|
|
||||||
it.dependsOn(setupTask)
|
it.dependsOn(setupTask)
|
||||||
it.inputs.property("ignoreScripts", { yarnRootExtension.ignoreScripts })
|
it.inputs.property("yarnIgnoreScripts", { yarnRootExtension.ignoreScripts })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
yarnRootExtension.nodeJsEnvironment.value(
|
||||||
|
project.provider {
|
||||||
|
nodeJs.requireConfigured()
|
||||||
|
}
|
||||||
|
).disallowChanges()
|
||||||
|
|
||||||
tasks.register("yarn" + CleanDataTask.NAME_SUFFIX, CleanDataTask::class.java) {
|
tasks.register("yarn" + CleanDataTask.NAME_SUFFIX, CleanDataTask::class.java) {
|
||||||
it.cleanableStoreProvider = provider { yarnRootExtension.requireConfigured().cleanableStore }
|
it.cleanableStoreProvider = provider { yarnRootExtension.requireConfigured().cleanableStore }
|
||||||
it.description = "Clean unused local yarn version"
|
it.description = "Clean unused local yarn version"
|
||||||
}
|
}
|
||||||
|
|
||||||
val packageJsonUmbrella = nodeJsTaskProviders
|
|
||||||
.packageJsonUmbrellaTaskProvider
|
|
||||||
|
|
||||||
yarnRootExtension.rootPackageJsonTaskProvider.configure {
|
|
||||||
it.dependsOn(packageJsonUmbrella)
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.register(STORE_YARN_LOCK_NAME, YarnLockStoreTask::class.java) { task ->
|
tasks.register(STORE_YARN_LOCK_NAME, YarnLockStoreTask::class.java) { task ->
|
||||||
task.dependsOn(kotlinNpmInstall)
|
task.dependsOn(kotlinNpmInstall)
|
||||||
task.inputFile.set(nodeJs.rootPackageDirectory.map { it.file("yarn.lock") })
|
task.inputFile.set(nodeJs.rootPackageDirectory.map { it.file(LockCopyTask.YARN_LOCK) })
|
||||||
task.outputDirectory.set(yarnRootExtension.lockFileDirectory)
|
task.outputDirectory.set(yarnRootExtension.lockFileDirectory)
|
||||||
task.fileName.set(yarnRootExtension.lockFileName)
|
task.fileName.set(yarnRootExtension.lockFileName)
|
||||||
|
|
||||||
task.yarnLockMismatchReport = provider { yarnRootExtension.requireConfigured().yarnLockMismatchReport }
|
task.lockFileMismatchReport.value(
|
||||||
task.reportNewYarnLock = provider { yarnRootExtension.requireConfigured().reportNewYarnLock }
|
provider { yarnRootExtension.requireConfigured().yarnLockMismatchReport.toLockFileMismatchReport() }
|
||||||
task.yarnLockAutoReplace = provider { yarnRootExtension.requireConfigured().yarnLockAutoReplace }
|
).disallowChanges()
|
||||||
|
task.reportNewLockFile.value(
|
||||||
|
provider { yarnRootExtension.requireConfigured().reportNewYarnLock }
|
||||||
|
).disallowChanges()
|
||||||
|
task.lockFileAutoReplace.value(
|
||||||
|
provider { yarnRootExtension.requireConfigured().yarnLockAutoReplace }
|
||||||
|
).disallowChanges()
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register(UPGRADE_YARN_LOCK, YarnLockCopyTask::class.java) { task ->
|
tasks.register(UPGRADE_YARN_LOCK, YarnLockCopyTask::class.java) { task ->
|
||||||
task.dependsOn(kotlinNpmInstall)
|
task.dependsOn(kotlinNpmInstall)
|
||||||
task.inputFile.set(nodeJs.rootPackageDirectory.map { it.file("yarn.lock") })
|
task.inputFile.set(nodeJs.rootPackageDirectory.map { it.file(LockCopyTask.YARN_LOCK) })
|
||||||
task.outputDirectory.set(yarnRootExtension.lockFileDirectory)
|
task.outputDirectory.set(yarnRootExtension.lockFileDirectory)
|
||||||
task.fileName.set(yarnRootExtension.lockFileName)
|
task.fileName.set(yarnRootExtension.lockFileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
val restoreYarnLock = tasks.register(RESTORE_YARN_LOCK_NAME, YarnLockCopyTask::class.java) {
|
tasks.register(RESTORE_YARN_LOCK_NAME, YarnLockCopyTask::class.java) {
|
||||||
val lockFile = yarnRootExtension.lockFileDirectory.resolve(yarnRootExtension.lockFileName)
|
val lockFile = yarnRootExtension.lockFileDirectory.resolve(yarnRootExtension.lockFileName)
|
||||||
it.inputFile.set(yarnRootExtension.lockFileDirectory.resolve(yarnRootExtension.lockFileName))
|
it.inputFile.set(yarnRootExtension.lockFileDirectory.resolve(yarnRootExtension.lockFileName))
|
||||||
it.outputDirectory.set(nodeJs.rootPackageDirectory)
|
it.outputDirectory.set(nodeJs.rootPackageDirectory)
|
||||||
it.fileName.set("yarn.lock")
|
it.fileName.set(LockCopyTask.YARN_LOCK)
|
||||||
it.onlyIf {
|
it.onlyIf {
|
||||||
lockFile.exists()
|
lockFile.exists()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlinNpmInstall.configure {
|
yarnRootExtension.preInstallTasks.value(
|
||||||
it.dependsOn(restoreYarnLock)
|
listOf(yarnRootExtension.restoreYarnLockTaskProvider)
|
||||||
}
|
).disallowChanges()
|
||||||
}
|
|
||||||
|
|
||||||
// Yes, we need to break Task Configuration Avoidance here
|
yarnRootExtension.postInstallTasks.value(
|
||||||
// In case when we need to create package.json's files and execute kotlinNpmInstall,
|
listOf(yarnRootExtension.storeYarnLockTaskProvider)
|
||||||
// We need to configure all RequiresNpmDependencies tasks to install them,
|
).disallowChanges()
|
||||||
// Because we need to persist yarn.lock
|
|
||||||
// We execute this block in configure phase of rootPackageJson to be sure,
|
|
||||||
// That Task Configuration Avoidance will not be broken for tasks not related with NPM installing
|
|
||||||
// https://youtrack.jetbrains.com/issue/KT-48241
|
|
||||||
private fun configureRequiresNpmDependencies(
|
|
||||||
project: Project,
|
|
||||||
rootPackageJson: TaskProvider<RootPackageJsonTask>,
|
|
||||||
) {
|
|
||||||
val fn: (Project) -> Unit = {
|
|
||||||
it.tasks.implementing(RequiresNpmDependencies::class)
|
|
||||||
.forEach {}
|
|
||||||
}
|
|
||||||
rootPackageJson.configure {
|
|
||||||
project.allprojects
|
|
||||||
.forEach { project ->
|
|
||||||
if (it.state.executed) {
|
|
||||||
fn(project)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
project.allprojects
|
|
||||||
.forEach {
|
|
||||||
if (!it.state.executed) {
|
|
||||||
it.afterEvaluate { project ->
|
|
||||||
rootPackageJson.configure {
|
|
||||||
fn(project)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -164,5 +114,9 @@ open class YarnPlugin : Plugin<Project> {
|
|||||||
rootProject.plugins.apply(YarnPlugin::class.java)
|
rootProject.plugins.apply(YarnPlugin::class.java)
|
||||||
return rootProject.extensions.getByName(YarnRootExtension.YARN) as YarnRootExtension
|
return rootProject.extensions.getByName(YarnRootExtension.YARN) as YarnRootExtension
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const val STORE_YARN_LOCK_NAME = "kotlinStoreYarnLock"
|
||||||
|
const val RESTORE_YARN_LOCK_NAME = "kotlinRestoreYarnLock"
|
||||||
|
const val UPGRADE_YARN_LOCK = "kotlinUpgradeYarnLock"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+37
-10
@@ -7,17 +7,24 @@ package org.jetbrains.kotlin.gradle.targets.js.yarn
|
|||||||
|
|
||||||
import org.gradle.api.Action
|
import org.gradle.api.Action
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.Task
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.gradle.api.provider.ListProperty
|
||||||
import org.gradle.api.tasks.TaskProvider
|
import org.gradle.api.tasks.TaskProvider
|
||||||
import org.jetbrains.kotlin.gradle.logging.kotlinInfo
|
import org.jetbrains.kotlin.gradle.logging.kotlinInfo
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.AbstractSettings
|
import org.jetbrains.kotlin.gradle.targets.js.AbstractSettings
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsEnv
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NpmApiExtension
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.Platform
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.Platform
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.RootPackageJsonTask
|
import org.jetbrains.kotlin.gradle.targets.js.npm.LockCopyTask
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin.Companion.RESTORE_YARN_LOCK_NAME
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin.Companion.STORE_YARN_LOCK_NAME
|
||||||
import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore
|
import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
open class YarnRootExtension(
|
open class YarnRootExtension(
|
||||||
val project: Project
|
val project: Project
|
||||||
) : AbstractSettings<YarnEnv>() {
|
) : AbstractSettings<YarnEnv>(), NpmApiExtension<YarnEnvironment, Yarn> {
|
||||||
init {
|
init {
|
||||||
check(project == project.rootProject)
|
check(project == project.rootProject)
|
||||||
}
|
}
|
||||||
@@ -26,6 +33,24 @@ open class YarnRootExtension(
|
|||||||
project.logger.kotlinInfo("Storing cached files in $it")
|
project.logger.kotlinInfo("Storing cached files in $it")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val packageManager: Yarn by lazy {
|
||||||
|
Yarn()
|
||||||
|
}
|
||||||
|
|
||||||
|
override val environment: YarnEnvironment by lazy {
|
||||||
|
requireConfigured().asYarnEnvironment
|
||||||
|
}
|
||||||
|
|
||||||
|
override val additionalInstallOutput: FileCollection = project.objects.fileCollection().from(
|
||||||
|
{
|
||||||
|
nodeJsEnvironment.get().rootPackageDir.resolve(LockCopyTask.YARN_LOCK)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
override val preInstallTasks: ListProperty<TaskProvider<*>> = project.objects.listProperty(TaskProvider::class.java)
|
||||||
|
|
||||||
|
override val postInstallTasks: ListProperty<TaskProvider<*>> = project.objects.listProperty(TaskProvider::class.java)
|
||||||
|
|
||||||
override var installationDir by Property(gradleHome.resolve("yarn"))
|
override var installationDir by Property(gradleHome.resolve("yarn"))
|
||||||
|
|
||||||
override var downloadBaseUrl: String? by Property("https://github.com/yarnpkg/yarn/releases/download")
|
override var downloadBaseUrl: String? by Property("https://github.com/yarnpkg/yarn/releases/download")
|
||||||
@@ -34,8 +59,8 @@ open class YarnRootExtension(
|
|||||||
override var command by Property("yarn")
|
override var command by Property("yarn")
|
||||||
|
|
||||||
override var download by Property(true)
|
override var download by Property(true)
|
||||||
var lockFileName by Property("yarn.lock")
|
var lockFileName by Property(LockCopyTask.YARN_LOCK)
|
||||||
var lockFileDirectory: File by Property(project.rootDir.resolve("kotlin-js-store"))
|
var lockFileDirectory: File by Property(project.rootDir.resolve(LockCopyTask.KOTLIN_JS_STORE))
|
||||||
|
|
||||||
var ignoreScripts by Property(true)
|
var ignoreScripts by Property(true)
|
||||||
|
|
||||||
@@ -50,11 +75,6 @@ open class YarnRootExtension(
|
|||||||
.withType(YarnSetupTask::class.java)
|
.withType(YarnSetupTask::class.java)
|
||||||
.named(YarnSetupTask.NAME)
|
.named(YarnSetupTask.NAME)
|
||||||
|
|
||||||
val rootPackageJsonTaskProvider: TaskProvider<RootPackageJsonTask>
|
|
||||||
get() = project.tasks
|
|
||||||
.withType(RootPackageJsonTask::class.java)
|
|
||||||
.named(RootPackageJsonTask.NAME)
|
|
||||||
|
|
||||||
internal val platform: org.gradle.api.provider.Property<Platform> = project.objects.property(Platform::class.java)
|
internal val platform: org.gradle.api.provider.Property<Platform> = project.objects.property(Platform::class.java)
|
||||||
|
|
||||||
var resolutions: MutableList<YarnResolution> by Property(mutableListOf())
|
var resolutions: MutableList<YarnResolution> by Property(mutableListOf())
|
||||||
@@ -72,6 +92,8 @@ open class YarnRootExtension(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal val nodeJsEnvironment: org.gradle.api.provider.Property<NodeJsEnv> = project.objects.property(NodeJsEnv::class.java)
|
||||||
|
|
||||||
override fun finalizeConfiguration(): YarnEnv {
|
override fun finalizeConfiguration(): YarnEnv {
|
||||||
val cleanableStore = CleanableStore[installationDir.path]
|
val cleanableStore = CleanableStore[installationDir.path]
|
||||||
|
|
||||||
@@ -93,7 +115,6 @@ open class YarnRootExtension(
|
|||||||
cleanableStore = cleanableStore,
|
cleanableStore = cleanableStore,
|
||||||
dir = home,
|
dir = home,
|
||||||
executable = getExecutable("yarn", command, "cmd"),
|
executable = getExecutable("yarn", command, "cmd"),
|
||||||
standalone = !download,
|
|
||||||
ivyDependency = "com.yarnpkg:yarn:$version@tar.gz",
|
ivyDependency = "com.yarnpkg:yarn:$version@tar.gz",
|
||||||
ignoreScripts = ignoreScripts,
|
ignoreScripts = ignoreScripts,
|
||||||
yarnLockMismatchReport = yarnLockMismatchReport,
|
yarnLockMismatchReport = yarnLockMismatchReport,
|
||||||
@@ -103,6 +124,12 @@ open class YarnRootExtension(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val restoreYarnLockTaskProvider: TaskProvider<YarnLockCopyTask>
|
||||||
|
get() = project.tasks.withType(YarnLockCopyTask::class.java).named(RESTORE_YARN_LOCK_NAME)
|
||||||
|
|
||||||
|
val storeYarnLockTaskProvider: TaskProvider<YarnLockStoreTask>
|
||||||
|
get() = project.tasks.withType(YarnLockStoreTask::class.java).named(STORE_YARN_LOCK_NAME)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val YARN: String = "kotlinYarn"
|
const val YARN: String = "kotlinYarn"
|
||||||
|
|
||||||
|
|||||||
+10
-14
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.gradle.utils.getFile
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class YarnWorkspaces : YarnBasics() {
|
class YarnWorkspaces : YarnBasics() {
|
||||||
override fun preparedFiles(nodeJs: NpmEnvironment): Collection<File> {
|
override fun preparedFiles(nodeJs: NodeJsEnvironment): Collection<File> {
|
||||||
return listOf(
|
return listOf(
|
||||||
nodeJs
|
nodeJs
|
||||||
.rootPackageDir
|
.rootPackageDir
|
||||||
@@ -22,28 +22,26 @@ class YarnWorkspaces : YarnBasics() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun prepareRootProject(
|
override fun prepareRootProject(
|
||||||
nodeJs: NpmEnvironment,
|
nodeJs: NodeJsEnvironment,
|
||||||
|
yarn: YarnEnvironment,
|
||||||
rootProjectName: String,
|
rootProjectName: String,
|
||||||
rootProjectVersion: String,
|
rootProjectVersion: String,
|
||||||
logger: Logger,
|
|
||||||
subProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
subProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
resolutions: Map<String, String>,
|
|
||||||
) {
|
) {
|
||||||
return prepareRootPackageJson(
|
return prepareRootPackageJson(
|
||||||
nodeJs,
|
nodeJs,
|
||||||
rootProjectName,
|
rootProjectName,
|
||||||
rootProjectVersion,
|
rootProjectVersion,
|
||||||
logger,
|
|
||||||
subProjects,
|
subProjects,
|
||||||
resolutions
|
yarn.yarnResolutions
|
||||||
|
.associate { it.path to it.toVersionString() },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun prepareRootPackageJson(
|
private fun prepareRootPackageJson(
|
||||||
nodeJs: NpmEnvironment,
|
nodeJs: NodeJsEnvironment,
|
||||||
rootProjectName: String,
|
rootProjectName: String,
|
||||||
rootProjectVersion: String,
|
rootProjectVersion: String,
|
||||||
logger: Logger,
|
|
||||||
npmProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
npmProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
resolutions: Map<String, String>
|
resolutions: Map<String, String>
|
||||||
) {
|
) {
|
||||||
@@ -52,7 +50,6 @@ class YarnWorkspaces : YarnBasics() {
|
|||||||
saveRootProjectWorkspacesPackageJson(
|
saveRootProjectWorkspacesPackageJson(
|
||||||
rootProjectName,
|
rootProjectName,
|
||||||
rootProjectVersion,
|
rootProjectVersion,
|
||||||
logger,
|
|
||||||
npmProjects,
|
npmProjects,
|
||||||
resolutions,
|
resolutions,
|
||||||
rootPackageJsonFile
|
rootPackageJsonFile
|
||||||
@@ -62,7 +59,7 @@ class YarnWorkspaces : YarnBasics() {
|
|||||||
override fun resolveRootProject(
|
override fun resolveRootProject(
|
||||||
services: ServiceRegistry,
|
services: ServiceRegistry,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
nodeJs: NpmEnvironment,
|
nodeJs: NodeJsEnvironment,
|
||||||
yarn: YarnEnvironment,
|
yarn: YarnEnvironment,
|
||||||
npmProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
npmProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
cliArgs: List<String>
|
cliArgs: List<String>
|
||||||
@@ -75,7 +72,7 @@ class YarnWorkspaces : YarnBasics() {
|
|||||||
nodeJs,
|
nodeJs,
|
||||||
yarn,
|
yarn,
|
||||||
nodeJsWorldDir,
|
nodeJsWorldDir,
|
||||||
NpmApi.resolveOperationDescription("yarn"),
|
NpmApiExecution.resolveOperationDescription("yarn"),
|
||||||
cliArgs
|
cliArgs
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -83,7 +80,6 @@ class YarnWorkspaces : YarnBasics() {
|
|||||||
private fun saveRootProjectWorkspacesPackageJson(
|
private fun saveRootProjectWorkspacesPackageJson(
|
||||||
rootProjectName: String,
|
rootProjectName: String,
|
||||||
rootProjectVersion: String,
|
rootProjectVersion: String,
|
||||||
logger: Logger,
|
|
||||||
npmProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
npmProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
resolutions: Map<String, String>,
|
resolutions: Map<String, String>,
|
||||||
rootPackageJsonFile: File
|
rootPackageJsonFile: File
|
||||||
@@ -94,10 +90,10 @@ class YarnWorkspaces : YarnBasics() {
|
|||||||
|
|
||||||
val npmProjectWorkspaces = npmProjects.map { it.npmProjectDir.getFile().relativeTo(nodeJsWorldDir).path }
|
val npmProjectWorkspaces = npmProjects.map { it.npmProjectDir.getFile().relativeTo(nodeJsWorldDir).path }
|
||||||
val importedProjectWorkspaces =
|
val importedProjectWorkspaces =
|
||||||
YarnImportedPackagesVersionResolver(logger, npmProjects, nodeJsWorldDir).resolveAndUpdatePackages()
|
NpmImportedPackagesVersionResolver(npmProjects, nodeJsWorldDir).resolveAndUpdatePackages()
|
||||||
|
|
||||||
rootPackageJson.workspaces = npmProjectWorkspaces + importedProjectWorkspaces
|
rootPackageJson.workspaces = npmProjectWorkspaces + importedProjectWorkspaces
|
||||||
rootPackageJson.resolutions = resolutions
|
rootPackageJson.customField("resolutions", resolutions)
|
||||||
rootPackageJson.saveTo(
|
rootPackageJson.saveTo(
|
||||||
rootPackageJsonFile
|
rootPackageJsonFile
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user