Gradle, npm: resolve node_modules at parents, return local NodeJsExtension at NodeJsPlugin.apply
This commit is contained in:
+11
-1
@@ -38,7 +38,7 @@ internal class KotlinJsCompilationTestsConfigurator(
|
||||
|
||||
fun configure() {
|
||||
// apply plugin (cannot do it lazy)
|
||||
val nodeJs = NodeJsPlugin[target.project]
|
||||
val nodeJs = NodeJsPlugin.apply(target.project).root
|
||||
|
||||
val testJs = project.createOrRegisterTask<KotlinJsTest>(testTaskName) { testJs ->
|
||||
testJs.group = LifecycleBasePlugin.VERIFICATION_GROUP
|
||||
@@ -56,6 +56,16 @@ internal class KotlinJsCompilationTestsConfigurator(
|
||||
testJs.configureConventions()
|
||||
}
|
||||
|
||||
testJs.doGetTask().useNodeJs { }
|
||||
|
||||
registerTestTask(testJs)
|
||||
|
||||
// project.afterEvaluate {
|
||||
// testJs.configure {
|
||||
// if (it.testFramework == null) {
|
||||
// it.useNodeJs { }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
+8
-5
@@ -9,6 +9,9 @@ import org.gradle.api.Project
|
||||
import org.jetbrains.kotlin.gradle.targets.js.npm.PackageJson
|
||||
|
||||
open class NodeJsExtension(val project: Project) {
|
||||
val root: NodeJsRootExtension
|
||||
get() = this as? NodeJsRootExtension ?: NodeJsRootExtension[project]
|
||||
|
||||
internal val packageJsonHandlers = mutableListOf<PackageJson.() -> Unit>()
|
||||
|
||||
fun packageJson(handler: PackageJson.() -> Unit) {
|
||||
@@ -16,9 +19,9 @@ open class NodeJsExtension(val project: Project) {
|
||||
}
|
||||
|
||||
companion object {
|
||||
operator fun get(project: Project): NodeJsExtension {
|
||||
NodeJsPlugin[project.rootProject]
|
||||
return project.extensions.getByName(NodeJsRootExtension.NODE_JS) as NodeJsExtension
|
||||
}
|
||||
operator fun get(project: Project) = NodeJsPlugin.apply(project)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val Project.nodeJs: NodeJsExtension
|
||||
get() = NodeJsExtension[this]
|
||||
+7
-18
@@ -4,10 +4,7 @@ import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.plugins.BasePlugin
|
||||
import org.gradle.api.tasks.Delete
|
||||
import org.jetbrains.kotlin.backend.common.onlyIf
|
||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension.Companion.NODE_JS
|
||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProjectLayout
|
||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmResolver
|
||||
|
||||
open class NodeJsPlugin : Plugin<Project> {
|
||||
override fun apply(project: Project): Unit = project.run {
|
||||
@@ -15,10 +12,10 @@ open class NodeJsPlugin : Plugin<Project> {
|
||||
"NodeJsPlugin can be applied only to root project"
|
||||
}
|
||||
|
||||
val nodeJs = this.extensions.create(NODE_JS, NodeJsRootExtension::class.java, this)
|
||||
this.extensions.create(NODE_JS, NodeJsRootExtension::class.java, this)
|
||||
tasks.create(NodeJsSetupTask.NAME, NodeJsSetupTask::class.java)
|
||||
|
||||
// setupCleanNodeModulesTask(project, nodeJs)
|
||||
setupCleanNodeModulesTask(project)
|
||||
|
||||
allprojects {
|
||||
if (it != project) {
|
||||
@@ -27,21 +24,13 @@ open class NodeJsPlugin : Plugin<Project> {
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupCleanNodeModulesTask(
|
||||
project: Project,
|
||||
nodeJs: NodeJsRootExtension
|
||||
) {
|
||||
private fun setupCleanNodeModulesTask(project: Project) {
|
||||
project.tasks.create("cleanNodeModules", Delete::class.java) {
|
||||
it.description = "Deletes node_modules and package.json file"
|
||||
it.group = BasePlugin.BUILD_GROUP
|
||||
|
||||
val npmProjectLayout = NpmProjectLayout[it.project]
|
||||
|
||||
project.delete(npmProjectLayout.nodeModulesDir)
|
||||
project.afterEvaluate {
|
||||
if (nodeJs.manageNodeModules) {
|
||||
project.delete(npmProjectLayout.packageJsonFile)
|
||||
}
|
||||
it.doLast {
|
||||
project.nodeJs.root.packageManager.cleanProject(project)
|
||||
}
|
||||
|
||||
project.tasks.maybeCreate(BasePlugin.CLEAN_TASK_NAME).dependsOn(it)
|
||||
@@ -49,10 +38,10 @@ open class NodeJsPlugin : Plugin<Project> {
|
||||
}
|
||||
|
||||
companion object {
|
||||
operator fun get(project: Project): NodeJsRootExtension {
|
||||
fun apply(project: Project): NodeJsExtension {
|
||||
val rootProject = project.rootProject
|
||||
rootProject.plugins.apply(NodeJsPlugin::class.java)
|
||||
return rootProject.extensions.getByName(NODE_JS) as NodeJsRootExtension
|
||||
return rootProject.extensions.getByName(NODE_JS) as NodeJsExtension
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+28
-27
@@ -28,37 +28,38 @@ open class NodeJsRootExtension(project: Project) : NodeJsExtension(project) {
|
||||
val nodeJsSetupTask: NodeJsSetupTask
|
||||
get() = project.tasks.getByName(NodeJsSetupTask.NAME) as NodeJsSetupTask
|
||||
|
||||
internal fun buildEnv(): NodeJsEnv {
|
||||
val platform = NodeJsPlatform.name
|
||||
val architecture = NodeJsPlatform.architecture
|
||||
internal val environment: NodeJsEnv
|
||||
get() {
|
||||
val platform = NodeJsPlatform.name
|
||||
val architecture = NodeJsPlatform.architecture
|
||||
|
||||
val nodeDir = installationDir.resolve("node-v$nodeVersion-$platform-$architecture")
|
||||
val isWindows = NodeJsPlatform.name == NodeJsPlatform.WIN
|
||||
val nodeBinDir = if (isWindows) nodeDir else nodeDir.resolve("bin")
|
||||
val nodeDir = installationDir.resolve("node-v$nodeVersion-$platform-$architecture")
|
||||
val isWindows = NodeJsPlatform.name == NodeJsPlatform.WIN
|
||||
val nodeBinDir = if (isWindows) nodeDir else nodeDir.resolve("bin")
|
||||
|
||||
fun getExecutable(command: String, customCommand: String, windowsExtension: String): String {
|
||||
val finalCommand = if (isWindows && customCommand == command) "$command.$windowsExtension" else customCommand
|
||||
return if (download) File(nodeBinDir, finalCommand).absolutePath else finalCommand
|
||||
fun getExecutable(command: String, customCommand: String, windowsExtension: String): String {
|
||||
val finalCommand = if (isWindows && customCommand == command) "$command.$windowsExtension" else customCommand
|
||||
return if (download) File(nodeBinDir, finalCommand).absolutePath else finalCommand
|
||||
}
|
||||
|
||||
fun getIvyDependency(): String {
|
||||
val type = if (isWindows) "zip" else "tar.gz"
|
||||
return "org.nodejs:node:$nodeVersion:$platform-$architecture@$type"
|
||||
}
|
||||
|
||||
return NodeJsEnv(
|
||||
nodeDir = nodeDir,
|
||||
nodeBinDir = nodeBinDir,
|
||||
nodeExecutable = getExecutable("node", nodeCommand, "exe"),
|
||||
npmExecutable = getExecutable("npm", npmCommand, "cmd"),
|
||||
platformName = platform,
|
||||
architectureName = architecture,
|
||||
ivyDependency = getIvyDependency()
|
||||
)
|
||||
}
|
||||
|
||||
fun getIvyDependency(): String {
|
||||
val type = if (isWindows) "zip" else "tar.gz"
|
||||
return "org.nodejs:node:$nodeVersion:$platform-$architecture@$type"
|
||||
}
|
||||
|
||||
return NodeJsEnv(
|
||||
nodeDir = nodeDir,
|
||||
nodeBinDir = nodeBinDir,
|
||||
nodeExecutable = getExecutable("node", nodeCommand, "exe"),
|
||||
npmExecutable = getExecutable("npm", npmCommand, "cmd"),
|
||||
platformName = platform,
|
||||
architectureName = architecture,
|
||||
ivyDependency = getIvyDependency()
|
||||
)
|
||||
}
|
||||
|
||||
internal fun executeSetup() {
|
||||
val nodeJsEnv = buildEnv()
|
||||
val nodeJsEnv = environment
|
||||
if (download) {
|
||||
if (!nodeJsEnv.nodeBinDir.isDirectory) {
|
||||
nodeJsSetupTask.exec()
|
||||
@@ -69,6 +70,6 @@ open class NodeJsRootExtension(project: Project) : NodeJsExtension(project) {
|
||||
companion object {
|
||||
const val NODE_JS: String = "nodeJs"
|
||||
|
||||
operator fun get(project: Project): NodeJsRootExtension = NodeJsPlugin[project]
|
||||
operator fun get(project: Project) = NodeJsPlugin.apply(project.rootProject) as NodeJsRootExtension
|
||||
}
|
||||
}
|
||||
|
||||
-13
@@ -12,7 +12,6 @@ import org.gradle.api.Project
|
||||
import org.gradle.process.ExecSpec
|
||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin
|
||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs
|
||||
import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile
|
||||
import java.io.File
|
||||
|
||||
class NpmProjectLayout(
|
||||
@@ -36,18 +35,6 @@ class NpmProjectLayout(
|
||||
exec.args = listOf(findModule(tool)) + args
|
||||
}
|
||||
|
||||
val hoistGradleNodeModules: Boolean
|
||||
get() = project.nodeJs.root.packageManager.getHoistGradleNodeModules(project)
|
||||
|
||||
val gradleNodeModulesDir: File
|
||||
get() =
|
||||
if (hoistGradleNodeModules) project.rootProject.npmProject.nodeModulesDir
|
||||
else nodeModulesDir
|
||||
|
||||
fun moduleOutput(compilationTask: Kotlin2JsCompile): File {
|
||||
return gradleNodeModulesDir.resolve(compilationTask.outputFile.name)
|
||||
}
|
||||
|
||||
@TailRecursive
|
||||
fun findModule(name: String, src: NpmProjectLayout = this): String {
|
||||
val file = nodeModulesDir.resolve(name)
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ internal class NpmResolver private constructor(val rootProject: Project) {
|
||||
class ResolvedNow(val resolution: ResolvedProject) : ResolutionCallResult()
|
||||
}
|
||||
|
||||
private val nodeJs = NodeJsPlugin.apply(rootProject)
|
||||
private val nodeJs = NodeJsPlugin.apply(rootProject).root
|
||||
private val packageManager = nodeJs.packageManager
|
||||
private val hoistGradleNodeModules = packageManager.getHoistGradleNodeModules(rootProject)
|
||||
private val npmPackages = mutableListOf<NpmPackage>()
|
||||
|
||||
+15
-6
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.targets.js.testing
|
||||
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.gradle.api.tasks.SkipWhenEmpty
|
||||
import org.gradle.process.internal.DefaultProcessForkOptions
|
||||
import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutionSpec
|
||||
import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies
|
||||
@@ -14,13 +15,14 @@ import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin
|
||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProjectLayout
|
||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmResolver
|
||||
import org.jetbrains.kotlin.gradle.targets.js.testing.karma.KotlinKarma
|
||||
import org.jetbrains.kotlin.gradle.targets.js.testing.nodejs.KotlinNodeJsTestRunner
|
||||
import org.jetbrains.kotlin.gradle.targets.js.testing.mocha.KotlinMocha
|
||||
import org.jetbrains.kotlin.gradle.targets.js.testing.nodejs.KotlinNodeJsTestRunner
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinTest
|
||||
|
||||
open class KotlinJsTest : KotlinTest() {
|
||||
@Internal
|
||||
private var testFramework: KotlinJsTestFramework = KotlinNodeJsTestRunner()
|
||||
@SkipWhenEmpty
|
||||
internal var testFramework: KotlinJsTestFramework? = null
|
||||
|
||||
@Input
|
||||
var debug: Boolean = false
|
||||
@@ -37,13 +39,20 @@ open class KotlinJsTest : KotlinTest() {
|
||||
|
||||
fun useKarma(body: KotlinKarma.() -> Unit) = use(KotlinKarma(), body)
|
||||
|
||||
private inline fun <T : KotlinJsTestFramework> use(runner: T, body: T.() -> Unit) {
|
||||
testFramework = runner.also(body)
|
||||
private inline fun <T : KotlinJsTestFramework> use(runner: T, body: T.() -> Unit): T {
|
||||
check(testFramework == null) {
|
||||
"testFramework already configured for task ${this.path}"
|
||||
}
|
||||
|
||||
val testFramework = runner.also(body)
|
||||
this.testFramework = testFramework
|
||||
|
||||
val dependenciesHolder = runtimeDependencyHandler
|
||||
if (dependenciesHolder != null) {
|
||||
testFramework.configure(dependenciesHolder)
|
||||
}
|
||||
|
||||
return testFramework
|
||||
}
|
||||
|
||||
override fun executeTests() {
|
||||
@@ -57,7 +66,7 @@ open class KotlinJsTest : KotlinTest() {
|
||||
NpmResolver.resolve(project)
|
||||
|
||||
forkOptions.workingDir = NpmProjectLayout[project].nodeWorkDir
|
||||
forkOptions.executable = NodeJsPlugin[project].buildEnv().nodeExecutable
|
||||
forkOptions.executable = NodeJsPlugin.apply(project).root.environment.nodeExecutable
|
||||
|
||||
val nodeJsArgs = mutableListOf<String>()
|
||||
|
||||
@@ -65,6 +74,6 @@ open class KotlinJsTest : KotlinTest() {
|
||||
nodeJsArgs.add("--inspect-brk")
|
||||
}
|
||||
|
||||
return testFramework.createTestExecutionSpec(this, forkOptions, nodeJsArgs)
|
||||
return testFramework!!.createTestExecutionSpec(this, forkOptions, nodeJsArgs)
|
||||
}
|
||||
}
|
||||
+1
-5
@@ -54,11 +54,7 @@ class KotlinNodeJsTestRunner : KotlinJsTestFramework {
|
||||
|
||||
val args = nodeJsArgs +
|
||||
testRuntimeNodeModules.map {
|
||||
npmProjectLayout.nodeModulesDir.resolve(it).also { file ->
|
||||
check(file.isFile) {
|
||||
"Cannot find ${file.canonicalPath}"
|
||||
}
|
||||
}.canonicalPath
|
||||
npmProjectLayout.findModule(it)
|
||||
} +
|
||||
cliArgs.toList()
|
||||
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ object Yarn : NpmApi {
|
||||
vararg args: String,
|
||||
npmProjectLayout: NpmProjectLayout = NpmProjectLayout[project]
|
||||
) {
|
||||
val nodeJsEnv = NodeJsPlugin.apply(project).environment
|
||||
val nodeJsEnv = NodeJsPlugin.apply(project).root.environment
|
||||
val yarnEnv = YarnPlugin.apply(project).environment
|
||||
|
||||
val packageJsonHashFile = project.packageJsonHashFile
|
||||
|
||||
+4
-2
@@ -15,14 +15,16 @@ open class YarnPlugin : Plugin<Project> {
|
||||
"YarnPlugin can be applied only to root project"
|
||||
}
|
||||
|
||||
val nodeJs = NodeJsPlugin.apply(this).root
|
||||
|
||||
this.extensions.create(YarnRootExtension.YARN, YarnRootExtension::class.java, this)
|
||||
tasks.create(YarnSetupTask.NAME, YarnSetupTask::class.java) {
|
||||
it.dependsOn(NodeJsPlugin[this].nodeJsSetupTask)
|
||||
it.dependsOn(nodeJs.nodeJsSetupTask)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
operator fun get(project: Project): YarnRootExtension {
|
||||
fun apply(project: Project): YarnRootExtension {
|
||||
val rootProject = project.rootProject
|
||||
rootProject.plugins.apply(YarnPlugin::class.java)
|
||||
return rootProject.extensions.getByName(YarnRootExtension.YARN) as YarnRootExtension
|
||||
|
||||
+17
-24
@@ -5,10 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.targets.js.yarn
|
||||
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.Project
|
||||
import org.jetbrains.kotlin.gradle.logging.kotlinInfo
|
||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin
|
||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs
|
||||
|
||||
open class YarnRootExtension(val project: Project) {
|
||||
private val gradleHome = project.gradle.gradleUserHomeDir.also {
|
||||
@@ -23,43 +23,36 @@ open class YarnRootExtension(val project: Project) {
|
||||
val yarnSetupTask: YarnSetupTask
|
||||
get() = project.tasks.getByName(YarnSetupTask.NAME) as YarnSetupTask
|
||||
|
||||
var useWorkspaces: Boolean = false
|
||||
var disableWorkspaces: Boolean = false
|
||||
|
||||
internal fun checkUseWorkspace(): Boolean = if (useWorkspaces) {
|
||||
check(NodeJsPlugin[project].manageNodeModules) {
|
||||
"Yarn workspace can be used only with `manageNodeModules`: (add `nodeJs { manageNodeModules = true }` to your root project)"
|
||||
}
|
||||
|
||||
true
|
||||
} else false
|
||||
val useWorkspaces: Boolean
|
||||
get() = project.nodeJs.root.manageNodeModules && !disableWorkspaces
|
||||
|
||||
internal fun executeSetup() {
|
||||
NodeJsPlugin[project].executeSetup()
|
||||
NodeJsPlugin.apply(project).root.executeSetup()
|
||||
|
||||
val env = buildEnv()
|
||||
val env = environment
|
||||
if (!env.home.isDirectory) {
|
||||
yarnSetupTask.setup()
|
||||
}
|
||||
}
|
||||
|
||||
internal fun buildEnv() = YarnEnv(
|
||||
downloadUrl = "$downloadBaseUrl/v$version/yarn-v$version.tar.gz",
|
||||
home = installationDir.resolve("yarn-v$version")
|
||||
)
|
||||
internal val environment
|
||||
get() = YarnEnv(
|
||||
downloadUrl = "$downloadBaseUrl/v$version/yarn-v$version.tar.gz",
|
||||
home = installationDir.resolve("yarn-v$version")
|
||||
)
|
||||
|
||||
companion object {
|
||||
const val YARN: String = "yarn"
|
||||
|
||||
operator fun get(project: Project): YarnRootExtension {
|
||||
val extension = project.extensions.findByType(YarnRootExtension::class.java)
|
||||
if (extension != null)
|
||||
return extension
|
||||
|
||||
val parentProject = project.parent
|
||||
if (parentProject != null)
|
||||
return get(parentProject)
|
||||
|
||||
throw GradleException("YarnRootExtension is not installed")
|
||||
val rootProject = project.rootProject
|
||||
rootProject.plugins.apply(YarnPlugin::class.java)
|
||||
return rootProject.extensions.getByName(YARN) as YarnRootExtension
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val Project.yarn: YarnRootExtension
|
||||
get() = YarnRootExtension[this]
|
||||
Reference in New Issue
Block a user