diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/NodeExePatcher.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/NodeExePatcher.kt index a7d3c8a505d..d942ac67ad6 100644 --- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/NodeExePatcher.kt +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/NodeExePatcher.kt @@ -4,9 +4,13 @@ package software.aws.toolkits.jetbrains.services.amazonq.lsp import com.intellij.execution.configurations.GeneralCommandLine +import com.intellij.util.system.CpuArch +import com.intellij.util.text.nullize +import software.aws.toolkits.core.utils.exists import software.aws.toolkits.core.utils.getLogger import software.aws.toolkits.core.utils.info import java.nio.file.Path +import java.nio.file.Paths /** * Hacky nonsense to support old glibc platforms like AL2 @@ -16,13 +20,14 @@ import java.nio.file.Path object NodeExePatcher { const val GLIBC_LINKER_VAR = "VSCODE_SERVER_CUSTOM_GLIBC_LINKER" const val GLIBC_PATH_VAR = "VSCODE_SERVER_CUSTOM_GLIBC_PATH" + const val INTERNAL_AARCH64_LINKER = "/opt/vsc-sysroot/lib/ld-linux-aarch64.so.1" + const val INTERNAL_X86_64_LINKER = "/opt/vsc-sysroot/lib/ld-linux-x86-64.so.2" + const val INTERNAL_GLIBC_PATH = "/opt/vsc-sysroot/lib/" fun patch(node: Path): GeneralCommandLine { - val linker = System.getenv(GLIBC_LINKER_VAR) - val glibc = System.getenv(GLIBC_PATH_VAR) val nodePath = node.toAbsolutePath().toString() - return if (!linker.isNullOrEmpty() && !glibc.isNullOrEmpty()) { + return if (!linker.isNullOrEmpty() && glibc.isNotEmpty() && Paths.get(linker).exists() && Paths.get(glibc).exists()) { GeneralCommandLine(linker) .withParameters("--library-path", glibc, nodePath) .also { @@ -32,4 +37,18 @@ object NodeExePatcher { GeneralCommandLine(nodePath) } } + + private val linker + get() = System.getenv(GLIBC_LINKER_VAR).nullize(true) ?: let { + if (CpuArch.isArm64()) { + INTERNAL_AARCH64_LINKER + } else if (CpuArch.isIntel64()) { + INTERNAL_X86_64_LINKER + } else { + null + } + } + + private val glibc + get() = System.getenv(GLIBC_PATH_VAR).nullize(true) ?: INTERNAL_GLIBC_PATH } diff --git a/plugins/amazonq/shared/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonq/lsp/NodeExePatcherTest.kt b/plugins/amazonq/shared/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonq/lsp/NodeExePatcherTest.kt index ece36e91cf0..9a0be9a6e67 100644 --- a/plugins/amazonq/shared/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonq/lsp/NodeExePatcherTest.kt +++ b/plugins/amazonq/shared/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonq/lsp/NodeExePatcherTest.kt @@ -4,31 +4,55 @@ package software.aws.toolkits.jetbrains.services.amazonq.lsp import com.intellij.execution.configurations.GeneralCommandLine +import com.intellij.testFramework.rules.TempDirectory +import com.intellij.testFramework.utils.io.createFile +import com.intellij.util.system.CpuArch import org.assertj.core.api.Assertions.assertThat +import org.junit.Assume.assumeTrue import org.junit.Rule import org.junit.Test import software.aws.toolkits.core.rules.EnvironmentVariableHelper -import kotlin.io.path.Path +import software.aws.toolkits.core.utils.exists +import java.nio.file.Paths class NodeExePatcherTest { @get:Rule val envVarHelper = EnvironmentVariableHelper() - private val pathToNode = Path("/path/to/node").toAbsolutePath().toString() + @get:Rule + val tempDir = TempDirectory() + + private val pathToNode = Paths.get("/path/to/node").toAbsolutePath().toString() @Test - fun `patches if path available`() { - envVarHelper[NodeExePatcher.GLIBC_LINKER_VAR] = "/opt/vsc-sysroot/lib/ld-linux-x86-64.so.2" - envVarHelper[NodeExePatcher.GLIBC_PATH_VAR] = "/opt/vsc-sysroot/lib/" + fun `patches if environment variables are available`() { + val path = tempDir.newDirectory("vsc-sysroot").toPath().toAbsolutePath() + val linker = Paths.get(path.toString(), "someSharedLibrary").createFile() + + envVarHelper[NodeExePatcher.GLIBC_LINKER_VAR] = linker.toString() + envVarHelper[NodeExePatcher.GLIBC_PATH_VAR] = path.toString() + + assertThat(NodeExePatcher.patch(Paths.get("/path/to/node"))) + .usingComparator(Comparator.comparing { it.commandLineString }) + .isEqualTo(GeneralCommandLine(linker.toString(), "--library-path", path.toString(), pathToNode)) + } + + @Test + fun `patches if hardcoded paths exists`() { + val path = Paths.get(NodeExePatcher.INTERNAL_GLIBC_PATH) + // too many permission issues otherwise + assumeTrue(path.exists()) + + val linker = Paths.get(if (CpuArch.isArm64()) NodeExePatcher.INTERNAL_AARCH64_LINKER else NodeExePatcher.INTERNAL_X86_64_LINKER) - assertThat(NodeExePatcher.patch(Path("/path/to/node"))) + assertThat(NodeExePatcher.patch(Paths.get("/path/to/node"))) .usingComparator(Comparator.comparing { it.commandLineString }) - .isEqualTo(GeneralCommandLine("/opt/vsc-sysroot/lib/ld-linux-x86-64.so.2", "--library-path", "/opt/vsc-sysroot/lib/", pathToNode)) + .isEqualTo(GeneralCommandLine(linker.toString(), "--library-path", path.toString(), pathToNode)) } @Test fun `noop if no patch available`() { - assertThat(NodeExePatcher.patch(Path("/path/to/node"))) + assertThat(NodeExePatcher.patch(Paths.get("/path/to/node"))) .usingComparator(Comparator.comparing { it.commandLineString }) .isEqualTo(GeneralCommandLine(pathToNode)) }