diff --git a/packages/gradle-plugin/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsExtension.kt b/packages/gradle-plugin/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsExtension.kt index d11f4612b54d..75ee3a58269d 100644 --- a/packages/gradle-plugin/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsExtension.kt +++ b/packages/gradle-plugin/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsExtension.kt @@ -76,7 +76,13 @@ abstract class ReactSettingsExtension @Inject constructor(val settings: Settings } } - checkAndUpdateCache(updateConfig, outputFile, outputFolder, lockFiles) + checkAndUpdateCache( + updateConfig, + outputFile, + outputFolder, + lockFiles, + settings.layout.rootDirectory.asFile, + ) linkLibraries(getLibrariesToAutolink(outputFile)) } @@ -123,12 +129,14 @@ abstract class ReactSettingsExtension @Inject constructor(val settings: Settings * @param cacheJsonConfig Our current cached autolinking.json config, which may exist * @param cacheFolder The folder we store our cached SHAs and config * @param lockFiles The [FileCollection] of the lockfiles to check. + * @param projectDir The root directory of the Android project being configured. * @return `true` if the cache needs to be rebuilt, `false` otherwise */ internal fun isCacheDirty( cacheJsonConfig: File, cacheFolder: File, lockFiles: FileCollection, + projectDir: File, ): Boolean { if (cacheJsonConfig.exists().not() || cacheJsonConfig.length() == 0L) { return true @@ -137,7 +145,8 @@ abstract class ReactSettingsExtension @Inject constructor(val settings: Settings if (lockFilesChanged) { return true } - return isConfigModelInvalid(JsonUtils.fromAutolinkingConfigJson(cacheJsonConfig)) + val model = JsonUtils.fromAutolinkingConfigJson(cacheJsonConfig) + return isConfigModelInvalid(model) || isConfigFromAnotherProjectDir(model, projectDir) } /** @@ -147,14 +156,16 @@ abstract class ReactSettingsExtension @Inject constructor(val settings: Settings * @param cacheJsonConfig Our current cached autolinking.json config, which may exist * @param cacheFolder The folder we store our cached SHAs and config * @param lockFiles The [FileCollection] of the lockfiles to check. + * @param projectDir The root directory of the Android project being configured. */ internal fun checkAndUpdateCache( updateJsonConfig: GenerateConfig, cacheJsonConfig: File, cacheFolder: File, lockFiles: FileCollection, + projectDir: File, ) { - if (isCacheDirty(cacheJsonConfig, cacheFolder, lockFiles)) { + if (isCacheDirty(cacheJsonConfig, cacheFolder, lockFiles, projectDir)) { val exitValue = updateJsonConfig.execute() if (exitValue != 0) { val prefixCommand = @@ -221,5 +232,13 @@ abstract class ReactSettingsExtension @Inject constructor(val settings: Settings internal fun isConfigModelInvalid(model: ModelAutolinkingConfigJson?) = model?.project?.android?.packageName == null + + internal fun isConfigFromAnotherProjectDir( + model: ModelAutolinkingConfigJson?, + projectDir: File, + ): Boolean { + val sourceDir = model?.project?.android?.sourceDir ?: return false + return File(sourceDir).canonicalFile != projectDir.canonicalFile + } } } diff --git a/packages/gradle-plugin/settings-plugin/src/test/kotlin/com/facebook/react/ReactSettingsExtensionTest.kt b/packages/gradle-plugin/settings-plugin/src/test/kotlin/com/facebook/react/ReactSettingsExtensionTest.kt index f85bd5d2b43a..9c203e902dab 100644 --- a/packages/gradle-plugin/settings-plugin/src/test/kotlin/com/facebook/react/ReactSettingsExtensionTest.kt +++ b/packages/gradle-plugin/settings-plugin/src/test/kotlin/com/facebook/react/ReactSettingsExtensionTest.kt @@ -273,7 +273,13 @@ class ReactSettingsExtensionTest { val monitoredUpdateConfig = createMonitoredUpdateConfig() - checkAndUpdateCache(monitoredUpdateConfig, outputFile, buildFolder, lockfileCollection) + checkAndUpdateCache( + monitoredUpdateConfig, + outputFile, + buildFolder, + lockfileCollection, + File("/"), + ) // The autolinking.json file is valid, SHA's are untouched therefore config should NOT be // refreshed @@ -294,7 +300,13 @@ class ReactSettingsExtensionTest { val monitoredUpdateConfig = createMonitoredUpdateConfig() - checkAndUpdateCache(monitoredUpdateConfig, outputFile, buildFolder, lockfileCollection) + checkAndUpdateCache( + monitoredUpdateConfig, + outputFile, + buildFolder, + lockfileCollection, + tempFolder.root, + ) // The autolinking.json file is invalid and should be refreshed assertThat(monitoredUpdateConfig.run).isTrue() @@ -327,12 +339,75 @@ class ReactSettingsExtensionTest { val monitoredUpdateConfig = createMonitoredUpdateConfig() - checkAndUpdateCache(monitoredUpdateConfig, outputFile, buildFolder, lockfileCollection) + checkAndUpdateCache( + monitoredUpdateConfig, + outputFile, + buildFolder, + lockfileCollection, + tempFolder.root, + ) // The autolinking.json file is invalid and should be refreshed assertThat(monitoredUpdateConfig.run).isTrue() } + @Test + fun checkAndUpdateConfigIfCachedConfigIsFromAnotherProjectDir() { + val project = ProjectBuilder.builder().withProjectDir(tempFolder.root).build() + val buildFolder = tempFolder.newFolder("build") + val generatedFolder = tempFolder.newFolder("build", "generated") + val outputFile = + File(generatedFolder, "autolinking.json").apply { + writeText( + """ + { + "root": "/old", + "reactNativePath": "/old/node_modules/react-native", + "reactNativeVersion": "0.75", + "dependencies": {}, + "healthChecks": [], + "platforms": { + "ios": {}, + "android": {} + }, + "assets": [], + "project": { + "ios": {}, + "android": { + "sourceDir": "/old/android", + "appName": "app", + "packageName": "com.TestApp", + "applicationId": "com.TestApp", + "mainActivity": ".MainActivity", + "assets": [] + } + } + } + """ + .trimIndent(), + ) + } + tempFolder.newFile("yarn.lock").apply { writeText("I'm a lockfile") } + val lockfileCollection = project.files("yarn.lock") + + // Prebuild the shas so that only the project location differs + checkAndUpdateLockfiles(lockfileCollection, buildFolder) + + val monitoredUpdateConfig = createMonitoredUpdateConfig() + + checkAndUpdateCache( + monitoredUpdateConfig, + outputFile, + buildFolder, + lockfileCollection, + tempFolder.root, + ) + + // The autolinking.json file was generated for a project in another folder and should be + // refreshed + assertThat(monitoredUpdateConfig.run).isTrue() + } + @Test fun isCacheDirty_withMissingAutolinkingFile_returnsTrue() { val project = ProjectBuilder.builder().withProjectDir(tempFolder.root).build() @@ -345,7 +420,14 @@ class ReactSettingsExtensionTest { val lockfiles = project.files("yarn.lock") val emptyConfigFile = File(tempFolder.newFolder("build", "autolinking"), "autolinking.json") - assertThat(ReactSettingsExtension.isCacheDirty(emptyConfigFile, buildFolder, lockfiles)) + assertThat( + ReactSettingsExtension.isCacheDirty( + emptyConfigFile, + buildFolder, + lockfiles, + tempFolder.root, + ), + ) .isTrue() } @@ -367,7 +449,14 @@ class ReactSettingsExtensionTest { .trimIndent(), ) - assertThat(ReactSettingsExtension.isCacheDirty(invalidConfigFile, buildFolder, lockfiles)) + assertThat( + ReactSettingsExtension.isCacheDirty( + invalidConfigFile, + buildFolder, + lockfiles, + tempFolder.root, + ), + ) .isTrue() } @@ -391,7 +480,14 @@ class ReactSettingsExtensionTest { .trimIndent(), ) - assertThat(ReactSettingsExtension.isCacheDirty(invalidConfigFile, buildFolder, lockfiles)) + assertThat( + ReactSettingsExtension.isCacheDirty( + invalidConfigFile, + buildFolder, + lockfiles, + tempFolder.root, + ), + ) .isTrue() } @@ -416,7 +512,14 @@ class ReactSettingsExtensionTest { .trimIndent(), ) - assertThat(ReactSettingsExtension.isCacheDirty(invalidConfigFile, buildFolder, lockfiles)) + assertThat( + ReactSettingsExtension.isCacheDirty( + invalidConfigFile, + buildFolder, + lockfiles, + tempFolder.root, + ), + ) .isTrue() } @@ -454,7 +557,14 @@ class ReactSettingsExtensionTest { .trimIndent(), ) - assertThat(ReactSettingsExtension.isCacheDirty(invalidConfigFile, buildFolder, lockfiles)) + assertThat( + ReactSettingsExtension.isCacheDirty( + invalidConfigFile, + buildFolder, + lockfiles, + tempFolder.root, + ), + ) .isTrue() }