Skip to content

Commit 5d560ca

Browse files
Krisztiaanfacebook-github-bot
authored andcommitted
fix: cliPath should handle absolute paths (#32983)
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
1 parent 0d2ee7c commit 5d560ca

File tree

3 files changed

+93
-19
lines changed

3 files changed

+93
-19
lines changed

packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PathUtils.kt

+16-2
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,18 @@ private fun detectCliPath(
6767
): String {
6868
// 1. preconfigured path
6969
if (preconfiguredCliPath != null) {
70-
return File(projectDir, preconfiguredCliPath).toString()
70+
val preconfiguredCliJsAbsolute = File(preconfiguredCliPath)
71+
if (preconfiguredCliJsAbsolute.exists()) {
72+
return preconfiguredCliJsAbsolute.absolutePath
73+
}
74+
val preconfiguredCliJsRelativeToReactRoot = File(reactRoot, preconfiguredCliPath)
75+
if (preconfiguredCliJsRelativeToReactRoot.exists()) {
76+
return preconfiguredCliJsRelativeToReactRoot.absolutePath
77+
}
78+
val preconfiguredCliJsRelativeToProject = File(projectDir, preconfiguredCliPath)
79+
if (preconfiguredCliJsRelativeToProject.exists()) {
80+
return preconfiguredCliJsRelativeToProject.absolutePath
81+
}
7182
}
7283

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

8394
if (nodeProcessOutput.isNotEmpty()) {
84-
return nodeProcessOutput
95+
val nodeModuleCliJs = File(nodeProcessOutput)
96+
if (nodeModuleCliJs.exists()) {
97+
return nodeModuleCliJs.absolutePath
98+
}
8599
}
86100

87101
// 3. cli.js in the root folder

packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/PathUtilsTest.kt

+39-2
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,47 @@ class PathUtilsTest {
5252
}
5353

5454
@Test
55-
fun detectedCliPath_withCliPathFromExtension() {
55+
fun detectedCliPath_withCliPathFromExtensionAbsolute() {
5656
val project = ProjectBuilder.builder().build()
5757
val extension = TestReactExtension(project)
58-
val expected = File(project.projectDir, "fake-cli.sh")
58+
val expected =
59+
File(project.projectDir, "abs/fake-cli.sh").apply {
60+
parentFile.mkdirs()
61+
writeText("<!-- nothing to see here -->")
62+
}
63+
extension.cliPath.set(project.projectDir + "/abs/fake-cli.sh")
64+
65+
val actual = detectedCliPath(project.projectDir, extension)
66+
67+
assertEquals(expected.toString(), actual)
68+
}
69+
70+
@Test
71+
fun detectedCliPath_withCliPathFromExtensionInReactFolder() {
72+
val project = ProjectBuilder.builder().build()
73+
val extension = TestReactExtension(project)
74+
val expected =
75+
File(project.projectDir, "/react-root/fake-cli.sh").apply {
76+
parentFile.mkdirs()
77+
writeText("<!-- nothing to see here -->")
78+
}
79+
extension.cliPath.set("fake-cli.sh")
80+
extension.reactRoot.set(project.projectDir + "/react-root")
81+
82+
val actual = detectedCliPath(project.projectDir, extension)
83+
84+
assertEquals(expected.toString(), actual)
85+
}
86+
87+
@Test
88+
fun detectedCliPath_withCliPathFromExtensionInProjectFolder() {
89+
val project = ProjectBuilder.builder().build()
90+
val extension = TestReactExtension(project)
91+
val expected =
92+
File(project.projectDir, "fake-cli.sh").apply {
93+
parentFile.mkdirs()
94+
writeText("<!-- nothing to see here -->")
95+
}
5996
extension.cliPath.set("fake-cli.sh")
6097

6198
val actual = detectedCliPath(project.projectDir, extension)

react.gradle

+38-15
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,6 @@ def detectEntryFile(config) {
2222
return "index.js";
2323
}
2424

25-
/**
26-
* Detects CLI location in a similar fashion to the React Native CLI
27-
*/
28-
def detectCliPath(config) {
29-
if (config.cliPath) {
30-
return "${projectDir}/${config.cliPath}"
31-
}
32-
if (new File("${projectDir}/../../node_modules/react-native/cli.js").exists()) {
33-
return "${projectDir}/../../node_modules/react-native/cli.js"
34-
}
35-
throw new Exception("Couldn't determine CLI location. " +
36-
"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`");
37-
}
38-
3925
def composeSourceMapsPath = config.composeSourceMapsPath ?: "node_modules/react-native/scripts/compose-source-maps.js"
4026
def bundleAssetName = config.bundleAssetName ?: "index.android.bundle"
4127
def entryFile = detectEntryFile(config)
@@ -46,6 +32,43 @@ def bundleConfig = config.bundleConfig ? "${reactRoot}/${config.bundleConfig}" :
4632
def enableVmCleanup = config.enableVmCleanup == null ? true : config.enableVmCleanup
4733
def hermesCommand = config.hermesCommand ?: "../../node_modules/hermes-engine/%OS-BIN%/hermesc"
4834

35+
/**
36+
* Detects CLI location in a similar fashion to the React Native CLI
37+
*/
38+
def detectCliPath(config, reactRoot) {
39+
// 1. preconfigured path
40+
if (config.cliPath) {
41+
def cliJsAbsolute = new File(config.cliPath)
42+
if (cliJsAbsolute.exists()) {
43+
return cliJsAbsolute.getAbsolutePath()
44+
}
45+
def cliJsRelativeToRoot = new File("${rootDir}/${config.cliPath}")
46+
if (cliJsRelativeToRoot.exists()) {
47+
return cliJsRelativeToRoot.getAbsolutePath()
48+
}
49+
def cliJsRelativeToProject = new File("${projectDir}/${config.cliPath}")
50+
if (cliJsRelativeToProject.exists()) {
51+
return cliJsRelativeToProject.getAbsolutePath()
52+
}
53+
}
54+
55+
// 2. node module path
56+
def cliJsFromNode = new File(["node", "--print", "require.resolve('react-native/cli').bin"].execute(null, rootDir).text.trim())
57+
if (cliJsFromNode.exists()) {
58+
return cliJsFromNode.getAbsolutePath()
59+
}
60+
61+
// 3. cli.js in the root folder
62+
def rootCliJs = new File(reactRoot, "node_modules/react-native/cli.js")
63+
if (rootCliJs.exists()) {
64+
return rootCliJs.getAbsolutePath()
65+
}
66+
67+
throw new Exception("Couldn't determine CLI location. " +
68+
"Please set `project.ext.react.cliPath` to the path of the react-native cli.js file. " +
69+
"This file typically resides in `node_modules/react-native/cli.js`");
70+
}
71+
4972
def reactNativeDevServerPort() {
5073
def value = project.getProperties().get("reactNativeDevServerPort")
5174
return value != null ? value : "8081"
@@ -164,7 +187,7 @@ afterEvaluate {
164187

165188
// Additional node and packager commandline arguments
166189
def nodeExecutableAndArgs = config.nodeExecutableAndArgs ?: ["node"]
167-
def cliPath = detectCliPath(config)
190+
def cliPath = detectCliPath(config, reactRoot)
168191

169192
def execCommand = []
170193

0 commit comments

Comments
 (0)