Skip to content

Commit

Permalink
Fix issue #100: drop support of Node.js versions older than 10.x (end…
Browse files Browse the repository at this point in the history
… of life).
  • Loading branch information
bsautel committed May 5, 2020
1 parent 45e52de commit b1d5838
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 195 deletions.
52 changes: 8 additions & 44 deletions src/main/kotlin/com/github/gradle/node/task/NodeSetupTask.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import com.github.gradle.node.NodeExtension
import com.github.gradle.node.NodePlugin
import com.github.gradle.node.util.PlatformHelper
import com.github.gradle.node.variant.VariantComputer
import com.github.gradle.node.variant.VariantComputer.Dependency
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputDirectory
Expand All @@ -21,9 +20,8 @@ open class NodeSetupTask : DefaultTask() {
val download by lazy { nodeExtension.download }

@get:Input
val dependency by lazy {
variantComputer.computeDependency(nodeExtension)
.map { Pair(it.archiveDependency, it.exeDependency) }
val archiveDependency by lazy {
variantComputer.computeArchiveDependency(nodeExtension)
}

@get:OutputDirectory
Expand All @@ -42,56 +40,25 @@ open class NodeSetupTask : DefaultTask() {
@TaskAction
fun exec() {
addRepositoryIfNeeded()
val dependency = variantComputer.computeDependency(nodeExtension).get()
if (!dependency.exeDependency.isNullOrBlank()) {
copyNodeExe(dependency)
}
val archiveDependency = variantComputer.computeArchiveDependency(nodeExtension).get()
deleteExistingNode()
unpackNodeArchive(dependency)
unpackNodeArchive(archiveDependency)
setExecutableFlag()
}

private fun copyNodeExe(dependency: Dependency) {
val nodeDirProvider = variantComputer.computeNodeDir(nodeExtension)
val nodeBinDirProvider = variantComputer.computeNodeBinDir(nodeDirProvider)
project.copy {
from(getNodeExeFile(dependency))
into(nodeBinDirProvider)
rename("node.*\\.exe", "node.exe")
}
}

private fun deleteExistingNode() {
project.delete(nodeDir.get().dir("../"))
}

private fun unpackNodeArchive(dependency: Dependency) {
val nodeArchiveFile = getNodeArchiveFile(dependency)
private fun unpackNodeArchive(archiveDependency: String) {
val nodeArchiveFile = getNodeArchiveFile(archiveDependency)
val nodeDirProvider = variantComputer.computeNodeDir(nodeExtension)
val nodeBinDirProvider = variantComputer.computeNodeBinDir(nodeDirProvider)
if (nodeArchiveFile.name.endsWith("zip")) {
project.copy {
from(project.zipTree(nodeArchiveFile))
into(nodeDirProvider.map { it.dir("../") })
}
} else if (!dependency.exeDependency.isNullOrBlank()) {
// Remap lib/node_modules to node_modules (the same directory as node.exe) because that's how the zip dist does it
project.copy {
from(project.tarTree(nodeArchiveFile))
into(nodeBinDirProvider)
val nodeModulesPattern = Regex("""^.*?[\\/]lib[\\/](node_modules.*$)""")
eachFile {
val file = this
val matchResult = nodeModulesPattern.matchEntire(file.path)
if (matchResult != null) {
// Remap the file to the root
file.path = matchResult.groupValues[1]
} else {
file.exclude()
}
}
includeEmptyDirs = false
}
} else {
project.copy {
from(project.tarTree(nodeArchiveFile))
Expand Down Expand Up @@ -121,11 +88,8 @@ open class NodeSetupTask : DefaultTask() {
}
}

private fun getNodeExeFile(dependency: Dependency): File? =
dependency.exeDependency?.let { resolveSingle(it) }

private fun getNodeArchiveFile(dependency: Dependency): File =
resolveSingle(dependency.archiveDependency)
private fun getNodeArchiveFile(archiveDependency: String): File =
resolveSingle(archiveDependency)

private fun resolveSingle(name: String): File {
val dep = project.dependencies.create(name)
Expand Down
7 changes: 0 additions & 7 deletions src/main/kotlin/com/github/gradle/node/util/KotlinUtils.kt
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
package com.github.gradle.node.util

import java.util.*
import java.util.concurrent.TimeUnit

/**
* Tokenizes the given string into a list using the provided delimiter set.
*/
@Suppress("UNCHECKED_CAST")
internal fun String.tokenize(delimiters: String = " \t\n\r\u000C"): List<String> = StringTokenizer(this, delimiters).toList() as List<String>

/**
* Executes the given command and returns its output.
*
Expand Down
61 changes: 2 additions & 59 deletions src/main/kotlin/com/github/gradle/node/variant/VariantComputer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package com.github.gradle.node.variant
import com.github.gradle.node.NodeExtension
import com.github.gradle.node.util.PlatformHelper
import com.github.gradle.node.util.mapIf
import com.github.gradle.node.util.tokenize
import com.github.gradle.node.util.zip
import org.gradle.api.file.Directory
import org.gradle.api.provider.Provider
Expand Down Expand Up @@ -97,66 +96,10 @@ internal class VariantComputer @JvmOverloads constructor(
private fun computeProductBinDir(productDirProvider: Provider<Directory>) =
if (platformHelper.isWindows) productDirProvider else productDirProvider.map { it.dir("bin") }

fun computeDependency(nodeExtension: NodeExtension): Provider<Dependency> {
fun computeArchiveDependency(nodeExtension: NodeExtension): Provider<String> {
val osName = platformHelper.osName
val osArch = platformHelper.osArch
return if (platformHelper.isWindows) {
hasWindowsZip(nodeExtension).flatMap { windowsZip ->
if (windowsZip) {
computeArchiveDependency(nodeExtension, osName, osArch, "zip")
.map { archiveDependency -> Dependency(archiveDependency) }
} else {
val archiveDependencyProvider =
computeArchiveDependency(nodeExtension, "linux", "x86", "tar.gz")
val exeDependencyProvider = computeExeDependency(nodeExtension)
zip(archiveDependencyProvider, exeDependencyProvider)
.map { (archiveDependency, exeDependency) ->
Dependency(archiveDependency, exeDependency)
}
}
}
} else {
computeArchiveDependency(nodeExtension, osName, osArch, "tar.gz")
.map { archiveDependency -> Dependency(archiveDependency) }
}
}

internal data class Dependency(
val archiveDependency: String,
val exeDependency: String? = null
)

private fun hasWindowsZip(nodeExtension: NodeExtension): Provider<Boolean> {
return nodeExtension.version.map { version ->
val (majorVersion, minorVersion, microVersion) =
version.tokenize(".").map { it.toInt() }
majorVersion == 4 && minorVersion >= 5
|| majorVersion == 6 && (minorVersion > 2 || minorVersion == 2 && microVersion >= 1)
|| majorVersion > 6
}
}

private fun computeExeDependency(nodeExtension: NodeExtension): Provider<String> {
return nodeExtension.version.map { version ->
val majorVersion = version.tokenize(".").first().toInt()
if (majorVersion > 3) {
if (platformHelper.osArch == "x86") {
"org.nodejs:win-x86/node:${version}@exe"
} else {
"org.nodejs:win-x64/node:${version}@exe"
}
} else {
if (platformHelper.osArch == "x86") {
"org.nodejs:node:${version}@exe"
} else {
"org.nodejs:x64/node:${version}@exe"
}
}
}
}

private fun computeArchiveDependency(nodeExtension: NodeExtension, osName: String, osArch: String,
type: String): Provider<String> {
val type = if (platformHelper.isWindows) "zip" else "tar.gz"
return nodeExtension.version.map { version -> "org.nodejs:node:$version:$osName-$osArch@$type" }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,82 +23,7 @@ class VariantComputerTest extends Specification {
}

@Unroll
def "test variant on windows version <4 (#osArch)"() {
given:
def project = ProjectBuilder.builder().build()

props.setProperty("os.name", "Windows 8")
props.setProperty("os.arch", osArch)

def nodeExtension = new NodeExtension(project)
nodeExtension.download.set(true)
nodeExtension.version.set('5.12.0')
nodeExtension.workDir.set(project.layout.projectDirectory.dir(".gradle/node"))
def variantComputer = new VariantComputer()

when:
def computedDependency = variantComputer.computeDependency(nodeExtension)
def computedNodeDir = variantComputer.computeNodeDir(nodeExtension)
def computeNodeBinDir = variantComputer.computeNodeBinDir(computedNodeDir)
def computedNodeExec = variantComputer.computeNodeExec(nodeExtension, computeNodeBinDir)
def computedNpmScriptFile = variantComputer.computeNpmScriptFile(computedNodeDir, "npm")
def computedNpxScriptFile = variantComputer.computeNpmScriptFile(computedNodeDir, "npx")

then:
computedDependency.get().exeDependency == exeDependency
computedDependency.get().archiveDependency == 'org.nodejs:node:5.12.0:[email protected]'
computedNodeDir.get().toString().endsWith(NODE_BASE_PATH + nodeDir)
computeNodeBinDir.get().toString().endsWith(NODE_BASE_PATH + nodeDir)
computedNodeExec.get().toString().endsWith(NODE_BASE_PATH + nodeDir + PS + "node.exe")
computedNpmScriptFile.get().toString().endsWith(NODE_BASE_PATH + nodeDir + PS + "node_modules${PS}npm${PS}bin${PS}npm-cli.js")
computedNpxScriptFile.get().toString().endsWith(NODE_BASE_PATH + nodeDir + PS + "node_modules${PS}npm${PS}bin${PS}npx-cli.js")

where:
osArch | nodeDir | exeDependency
'x86' | 'node-v5.12.0-win-x86' | 'org.nodejs:win-x86/node:5.12.0@exe'
'x86_64' | 'node-v5.12.0-win-x64' | 'org.nodejs:win-x64/node:5.12.0@exe'
}

@Unroll
def "test variant on windows version 4.+ with exe (#osArch)"() {
given:
def project = ProjectBuilder.builder().build()
props.setProperty("os.name", "Windows 8")
props.setProperty("os.arch", osArch)
def nodeExtension = new NodeExtension(project)
nodeExtension.download.set(true)
nodeExtension.version.set('4.0.0')
nodeExtension.workDir.set(project.layout.projectDirectory.dir(".gradle/node"))
def variantComputer = new VariantComputer()
when:
def computedDependency = variantComputer.computeDependency(nodeExtension)
def computedNodeDir = variantComputer.computeNodeDir(nodeExtension)
def computedNodeBinDir = variantComputer.computeNodeBinDir(computedNodeDir)
def computedNodeExec = variantComputer.computeNodeExec(nodeExtension, computedNodeBinDir)
def computedNpmScriptFile = variantComputer.computeNpmScriptFile(computedNodeDir, "npm")
def computedNpxScriptFile = variantComputer.computeNpmScriptFile(computedNodeDir, "npx")
then:
computedDependency.get().exeDependency == exeDependency
computedDependency.get().archiveDependency == 'org.nodejs:node:4.0.0:[email protected]'
computedNodeDir.get().toString().endsWith(NODE_BASE_PATH + nodeDir)
computedNodeBinDir.get().toString().endsWith(NODE_BASE_PATH + nodeDir)
computedNodeExec.get().toString().endsWith(NODE_BASE_PATH + nodeDir + PS + "node.exe")
computedNpmScriptFile.get().toString().endsWith(NODE_BASE_PATH + nodeDir + PS + "node_modules${PS}npm${PS}bin${PS}npm-cli.js")
computedNpxScriptFile.get().toString().endsWith(NODE_BASE_PATH + nodeDir + PS + "node_modules${PS}npm${PS}bin${PS}npx-cli.js")
where:
osArch | nodeDir | exeDependency
'x86' | 'node-v4.0.0-win-x86' | 'org.nodejs:win-x86/node:4.0.0@exe'
'x86_64' | 'node-v4.0.0-win-x64' | 'org.nodejs:win-x64/node:4.0.0@exe'
}
@Unroll
def "test variant on windows without exe (#version #osArch)"() {
def "test variant on windows (#version #osArch)"() {
given:
def project = ProjectBuilder.builder().build()
Expand All @@ -116,16 +41,15 @@ class VariantComputerTest extends Specification {
def variantComputer = new VariantComputer()

when:
def computedDependency = variantComputer.computeDependency(nodeExtension)
def computedArchiveDependency = variantComputer.computeArchiveDependency(nodeExtension)
def computedNodeDir = variantComputer.computeNodeDir(nodeExtension)
def computedNodeBinDir = variantComputer.computeNodeBinDir(computedNodeDir)
def computedNodeExec = variantComputer.computeNodeExec(nodeExtension, computedNodeBinDir)
def computedNpmScriptFile = variantComputer.computeNpmScriptFile(computedNodeDir, "npm")
def computedNpxScriptFile = variantComputer.computeNpmScriptFile(computedNodeDir, "npx")

then:
computedDependency.get().exeDependency == null
computedDependency.get().archiveDependency == depName
computedArchiveDependency.get() == depName

computedNodeDir.get().toString().endsWith(NODE_BASE_PATH + nodeDir)
computedNodeBinDir.get().toString().endsWith(NODE_BASE_PATH + nodeDir)
Expand Down Expand Up @@ -158,16 +82,15 @@ class VariantComputerTest extends Specification {
def variantComputer = new VariantComputer()

when:
def computedDependency = variantComputer.computeDependency(nodeExtension)
def computedArchiveDependency = variantComputer.computeArchiveDependency(nodeExtension)
def computedNodeDir = variantComputer.computeNodeDir(nodeExtension)
def computedNodeBinDir = variantComputer.computeNodeBinDir(computedNodeDir)
def computedNodeExec = variantComputer.computeNodeExec(nodeExtension, computedNodeBinDir)
def computedNpmScriptFile = variantComputer.computeNpmScriptFile(computedNodeDir, "npm")
def computedNpxScriptFile = variantComputer.computeNpmScriptFile(computedNodeDir, "npx")

then:
computedDependency.get().exeDependency == null
computedDependency.get().archiveDependency == depName
computedArchiveDependency.get() == depName

computedNodeDir.get().toString().endsWith(NODE_BASE_PATH + nodeDir)
computedNodeBinDir.get().toString().endsWith(NODE_BASE_PATH + nodeDir + PS + 'bin')
Expand Down Expand Up @@ -204,16 +127,15 @@ class VariantComputerTest extends Specification {
def variantComputer = new VariantComputer(platformHelperSpy)
when:
def computedDependency = variantComputer.computeDependency(nodeExtension)
def computedArchiveDependency = variantComputer.computeArchiveDependency(nodeExtension)
def computedNodeDir = variantComputer.computeNodeDir(nodeExtension)
def computedNodeBinDir = variantComputer.computeNodeBinDir(computedNodeDir)
def computedNodeExec = variantComputer.computeNodeExec(nodeExtension, computedNodeBinDir)
def computedNpmScriptFile = variantComputer.computeNpmScriptFile(computedNodeDir, "npm")
def computedNpxScriptFile = variantComputer.computeNpmScriptFile(computedNodeDir, "npx")
then:
computedDependency.get().exeDependency == null
computedDependency.get().archiveDependency == depName
computedArchiveDependency.get() == depName
computedNodeDir.get().toString().endsWith(NODE_BASE_PATH + nodeDir)
computedNodeBinDir.get().toString().endsWith(NODE_BASE_PATH + nodeDir + PS + 'bin')
Expand Down

0 comments on commit b1d5838

Please sign in to comment.