Skip to content

Commit

Permalink
fix: cliPath should handle absolute paths (#32983)
Browse files Browse the repository at this point in the history
Summary:
Avoid breaking tools relying on absolute path for `cliPath`

## Changelog

[Android] [Fixed] - Enable cliPath to have an absolute path value

Pull Request resolved: #32983

Test Plan:
declare `cliPath` from `expo`:
```groovy
cliPath: new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/cli.js",
```
and run an android build

Reviewed By: ShikaSD

Differential Revision: D33843275

Pulled By: cortinico

fbshipit-source-id: 65f55a5e07a4ec0a6205d5f06f150377708c30cc
  • Loading branch information
Krisztiaan authored and facebook-github-bot committed Mar 15, 2022
1 parent 0d2ee7c commit 5d560ca
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,18 @@ private fun detectCliPath(
): String {
// 1. preconfigured path
if (preconfiguredCliPath != null) {
return File(projectDir, preconfiguredCliPath).toString()
val preconfiguredCliJsAbsolute = File(preconfiguredCliPath)
if (preconfiguredCliJsAbsolute.exists()) {
return preconfiguredCliJsAbsolute.absolutePath
}
val preconfiguredCliJsRelativeToReactRoot = File(reactRoot, preconfiguredCliPath)
if (preconfiguredCliJsRelativeToReactRoot.exists()) {
return preconfiguredCliJsRelativeToReactRoot.absolutePath
}
val preconfiguredCliJsRelativeToProject = File(projectDir, preconfiguredCliPath)
if (preconfiguredCliJsRelativeToProject.exists()) {
return preconfiguredCliJsRelativeToProject.absolutePath
}
}

// 2. node module path
Expand All @@ -81,7 +92,10 @@ private fun detectCliPath(
val nodeProcessOutput = nodeProcess.inputStream.use { it.bufferedReader().readText().trim() }

if (nodeProcessOutput.isNotEmpty()) {
return nodeProcessOutput
val nodeModuleCliJs = File(nodeProcessOutput)
if (nodeModuleCliJs.exists()) {
return nodeModuleCliJs.absolutePath
}
}

// 3. cli.js in the root folder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,47 @@ class PathUtilsTest {
}

@Test
fun detectedCliPath_withCliPathFromExtension() {
fun detectedCliPath_withCliPathFromExtensionAbsolute() {
val project = ProjectBuilder.builder().build()
val extension = TestReactExtension(project)
val expected = File(project.projectDir, "fake-cli.sh")
val expected =
File(project.projectDir, "abs/fake-cli.sh").apply {
parentFile.mkdirs()
writeText("<!-- nothing to see here -->")
}
extension.cliPath.set(project.projectDir + "/abs/fake-cli.sh")

val actual = detectedCliPath(project.projectDir, extension)

assertEquals(expected.toString(), actual)
}

@Test
fun detectedCliPath_withCliPathFromExtensionInReactFolder() {
val project = ProjectBuilder.builder().build()
val extension = TestReactExtension(project)
val expected =
File(project.projectDir, "/react-root/fake-cli.sh").apply {
parentFile.mkdirs()
writeText("<!-- nothing to see here -->")
}
extension.cliPath.set("fake-cli.sh")
extension.reactRoot.set(project.projectDir + "/react-root")

val actual = detectedCliPath(project.projectDir, extension)

assertEquals(expected.toString(), actual)
}

@Test
fun detectedCliPath_withCliPathFromExtensionInProjectFolder() {
val project = ProjectBuilder.builder().build()
val extension = TestReactExtension(project)
val expected =
File(project.projectDir, "fake-cli.sh").apply {
parentFile.mkdirs()
writeText("<!-- nothing to see here -->")
}
extension.cliPath.set("fake-cli.sh")

val actual = detectedCliPath(project.projectDir, extension)
Expand Down
53 changes: 38 additions & 15 deletions react.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,6 @@ def detectEntryFile(config) {
return "index.js";
}

/**
* Detects CLI location in a similar fashion to the React Native CLI
*/
def detectCliPath(config) {
if (config.cliPath) {
return "${projectDir}/${config.cliPath}"
}
if (new File("${projectDir}/../../node_modules/react-native/cli.js").exists()) {
return "${projectDir}/../../node_modules/react-native/cli.js"
}
throw new Exception("Couldn't determine CLI location. " +
"Please set `project.ext.react.cliPath` to the path of the react-native cli.js file. This file typically resides in `node_modules/react-native/cli.js`");
}

def composeSourceMapsPath = config.composeSourceMapsPath ?: "node_modules/react-native/scripts/compose-source-maps.js"
def bundleAssetName = config.bundleAssetName ?: "index.android.bundle"
def entryFile = detectEntryFile(config)
Expand All @@ -46,6 +32,43 @@ def bundleConfig = config.bundleConfig ? "${reactRoot}/${config.bundleConfig}" :
def enableVmCleanup = config.enableVmCleanup == null ? true : config.enableVmCleanup
def hermesCommand = config.hermesCommand ?: "../../node_modules/hermes-engine/%OS-BIN%/hermesc"

/**
* Detects CLI location in a similar fashion to the React Native CLI
*/
def detectCliPath(config, reactRoot) {
// 1. preconfigured path
if (config.cliPath) {
def cliJsAbsolute = new File(config.cliPath)
if (cliJsAbsolute.exists()) {
return cliJsAbsolute.getAbsolutePath()
}
def cliJsRelativeToRoot = new File("${rootDir}/${config.cliPath}")
if (cliJsRelativeToRoot.exists()) {
return cliJsRelativeToRoot.getAbsolutePath()
}
def cliJsRelativeToProject = new File("${projectDir}/${config.cliPath}")
if (cliJsRelativeToProject.exists()) {
return cliJsRelativeToProject.getAbsolutePath()
}
}

// 2. node module path
def cliJsFromNode = new File(["node", "--print", "require.resolve('react-native/cli').bin"].execute(null, rootDir).text.trim())
if (cliJsFromNode.exists()) {
return cliJsFromNode.getAbsolutePath()
}

// 3. cli.js in the root folder
def rootCliJs = new File(reactRoot, "node_modules/react-native/cli.js")
if (rootCliJs.exists()) {
return rootCliJs.getAbsolutePath()
}

throw new Exception("Couldn't determine CLI location. " +
"Please set `project.ext.react.cliPath` to the path of the react-native cli.js file. " +
"This file typically resides in `node_modules/react-native/cli.js`");
}

def reactNativeDevServerPort() {
def value = project.getProperties().get("reactNativeDevServerPort")
return value != null ? value : "8081"
Expand Down Expand Up @@ -164,7 +187,7 @@ afterEvaluate {

// Additional node and packager commandline arguments
def nodeExecutableAndArgs = config.nodeExecutableAndArgs ?: ["node"]
def cliPath = detectCliPath(config)
def cliPath = detectCliPath(config, reactRoot)

def execCommand = []

Expand Down

0 comments on commit 5d560ca

Please sign in to comment.