Skip to content

Commit 3a61c2c

Browse files
committed
Refresh Android autolinking cache when the project folder moves
1 parent 859d9b8 commit 3a61c2c

2 files changed

Lines changed: 140 additions & 11 deletions

File tree

‎packages/gradle-plugin/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsExtension.kt‎

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,13 @@ abstract class ReactSettingsExtension @Inject constructor(val settings: Settings
7676
}
7777
}
7878

79-
checkAndUpdateCache(updateConfig, outputFile, outputFolder, lockFiles)
79+
checkAndUpdateCache(
80+
updateConfig,
81+
outputFile,
82+
outputFolder,
83+
lockFiles,
84+
settings.layout.rootDirectory.asFile,
85+
)
8086

8187
linkLibraries(getLibrariesToAutolink(outputFile))
8288
}
@@ -123,12 +129,14 @@ abstract class ReactSettingsExtension @Inject constructor(val settings: Settings
123129
* @param cacheJsonConfig Our current cached autolinking.json config, which may exist
124130
* @param cacheFolder The folder we store our cached SHAs and config
125131
* @param lockFiles The [FileCollection] of the lockfiles to check.
132+
* @param projectDir The root directory of the Android project being configured.
126133
* @return `true` if the cache needs to be rebuilt, `false` otherwise
127134
*/
128135
internal fun isCacheDirty(
129136
cacheJsonConfig: File,
130137
cacheFolder: File,
131138
lockFiles: FileCollection,
139+
projectDir: File,
132140
): Boolean {
133141
if (cacheJsonConfig.exists().not() || cacheJsonConfig.length() == 0L) {
134142
return true
@@ -137,7 +145,8 @@ abstract class ReactSettingsExtension @Inject constructor(val settings: Settings
137145
if (lockFilesChanged) {
138146
return true
139147
}
140-
return isConfigModelInvalid(JsonUtils.fromAutolinkingConfigJson(cacheJsonConfig))
148+
val model = JsonUtils.fromAutolinkingConfigJson(cacheJsonConfig)
149+
return isConfigModelInvalid(model) || isConfigFromAnotherProjectDir(model, projectDir)
141150
}
142151

143152
/**
@@ -147,14 +156,16 @@ abstract class ReactSettingsExtension @Inject constructor(val settings: Settings
147156
* @param cacheJsonConfig Our current cached autolinking.json config, which may exist
148157
* @param cacheFolder The folder we store our cached SHAs and config
149158
* @param lockFiles The [FileCollection] of the lockfiles to check.
159+
* @param projectDir The root directory of the Android project being configured.
150160
*/
151161
internal fun checkAndUpdateCache(
152162
updateJsonConfig: GenerateConfig,
153163
cacheJsonConfig: File,
154164
cacheFolder: File,
155165
lockFiles: FileCollection,
166+
projectDir: File,
156167
) {
157-
if (isCacheDirty(cacheJsonConfig, cacheFolder, lockFiles)) {
168+
if (isCacheDirty(cacheJsonConfig, cacheFolder, lockFiles, projectDir)) {
158169
val exitValue = updateJsonConfig.execute()
159170
if (exitValue != 0) {
160171
val prefixCommand =
@@ -221,5 +232,13 @@ abstract class ReactSettingsExtension @Inject constructor(val settings: Settings
221232

222233
internal fun isConfigModelInvalid(model: ModelAutolinkingConfigJson?) =
223234
model?.project?.android?.packageName == null
235+
236+
internal fun isConfigFromAnotherProjectDir(
237+
model: ModelAutolinkingConfigJson?,
238+
projectDir: File,
239+
): Boolean {
240+
val sourceDir = model?.project?.android?.sourceDir ?: return false
241+
return File(sourceDir).canonicalFile != projectDir.canonicalFile
242+
}
224243
}
225244
}

‎packages/gradle-plugin/settings-plugin/src/test/kotlin/com/facebook/react/ReactSettingsExtensionTest.kt‎

Lines changed: 118 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,13 @@ class ReactSettingsExtensionTest {
273273

274274
val monitoredUpdateConfig = createMonitoredUpdateConfig()
275275

276-
checkAndUpdateCache(monitoredUpdateConfig, outputFile, buildFolder, lockfileCollection)
276+
checkAndUpdateCache(
277+
monitoredUpdateConfig,
278+
outputFile,
279+
buildFolder,
280+
lockfileCollection,
281+
File("/"),
282+
)
277283

278284
// The autolinking.json file is valid, SHA's are untouched therefore config should NOT be
279285
// refreshed
@@ -294,7 +300,13 @@ class ReactSettingsExtensionTest {
294300

295301
val monitoredUpdateConfig = createMonitoredUpdateConfig()
296302

297-
checkAndUpdateCache(monitoredUpdateConfig, outputFile, buildFolder, lockfileCollection)
303+
checkAndUpdateCache(
304+
monitoredUpdateConfig,
305+
outputFile,
306+
buildFolder,
307+
lockfileCollection,
308+
tempFolder.root,
309+
)
298310

299311
// The autolinking.json file is invalid and should be refreshed
300312
assertThat(monitoredUpdateConfig.run).isTrue()
@@ -327,12 +339,75 @@ class ReactSettingsExtensionTest {
327339

328340
val monitoredUpdateConfig = createMonitoredUpdateConfig()
329341

330-
checkAndUpdateCache(monitoredUpdateConfig, outputFile, buildFolder, lockfileCollection)
342+
checkAndUpdateCache(
343+
monitoredUpdateConfig,
344+
outputFile,
345+
buildFolder,
346+
lockfileCollection,
347+
tempFolder.root,
348+
)
331349

332350
// The autolinking.json file is invalid and should be refreshed
333351
assertThat(monitoredUpdateConfig.run).isTrue()
334352
}
335353

354+
@Test
355+
fun checkAndUpdateConfigIfCachedConfigIsFromAnotherProjectDir() {
356+
val project = ProjectBuilder.builder().withProjectDir(tempFolder.root).build()
357+
val buildFolder = tempFolder.newFolder("build")
358+
val generatedFolder = tempFolder.newFolder("build", "generated")
359+
val outputFile =
360+
File(generatedFolder, "autolinking.json").apply {
361+
writeText(
362+
"""
363+
{
364+
"root": "/old",
365+
"reactNativePath": "/old/node_modules/react-native",
366+
"reactNativeVersion": "0.75",
367+
"dependencies": {},
368+
"healthChecks": [],
369+
"platforms": {
370+
"ios": {},
371+
"android": {}
372+
},
373+
"assets": [],
374+
"project": {
375+
"ios": {},
376+
"android": {
377+
"sourceDir": "/old/android",
378+
"appName": "app",
379+
"packageName": "com.TestApp",
380+
"applicationId": "com.TestApp",
381+
"mainActivity": ".MainActivity",
382+
"assets": []
383+
}
384+
}
385+
}
386+
"""
387+
.trimIndent(),
388+
)
389+
}
390+
tempFolder.newFile("yarn.lock").apply { writeText("I'm a lockfile") }
391+
val lockfileCollection = project.files("yarn.lock")
392+
393+
// Prebuild the shas so that only the project location differs
394+
checkAndUpdateLockfiles(lockfileCollection, buildFolder)
395+
396+
val monitoredUpdateConfig = createMonitoredUpdateConfig()
397+
398+
checkAndUpdateCache(
399+
monitoredUpdateConfig,
400+
outputFile,
401+
buildFolder,
402+
lockfileCollection,
403+
tempFolder.root,
404+
)
405+
406+
// The autolinking.json file was generated for a project in another folder and should be
407+
// refreshed
408+
assertThat(monitoredUpdateConfig.run).isTrue()
409+
}
410+
336411
@Test
337412
fun isCacheDirty_withMissingAutolinkingFile_returnsTrue() {
338413
val project = ProjectBuilder.builder().withProjectDir(tempFolder.root).build()
@@ -345,7 +420,14 @@ class ReactSettingsExtensionTest {
345420
val lockfiles = project.files("yarn.lock")
346421
val emptyConfigFile = File(tempFolder.newFolder("build", "autolinking"), "autolinking.json")
347422

348-
assertThat(ReactSettingsExtension.isCacheDirty(emptyConfigFile, buildFolder, lockfiles))
423+
assertThat(
424+
ReactSettingsExtension.isCacheDirty(
425+
emptyConfigFile,
426+
buildFolder,
427+
lockfiles,
428+
tempFolder.root,
429+
),
430+
)
349431
.isTrue()
350432
}
351433

@@ -367,7 +449,14 @@ class ReactSettingsExtensionTest {
367449
.trimIndent(),
368450
)
369451

370-
assertThat(ReactSettingsExtension.isCacheDirty(invalidConfigFile, buildFolder, lockfiles))
452+
assertThat(
453+
ReactSettingsExtension.isCacheDirty(
454+
invalidConfigFile,
455+
buildFolder,
456+
lockfiles,
457+
tempFolder.root,
458+
),
459+
)
371460
.isTrue()
372461
}
373462

@@ -391,7 +480,14 @@ class ReactSettingsExtensionTest {
391480
.trimIndent(),
392481
)
393482

394-
assertThat(ReactSettingsExtension.isCacheDirty(invalidConfigFile, buildFolder, lockfiles))
483+
assertThat(
484+
ReactSettingsExtension.isCacheDirty(
485+
invalidConfigFile,
486+
buildFolder,
487+
lockfiles,
488+
tempFolder.root,
489+
),
490+
)
395491
.isTrue()
396492
}
397493

@@ -416,7 +512,14 @@ class ReactSettingsExtensionTest {
416512
.trimIndent(),
417513
)
418514

419-
assertThat(ReactSettingsExtension.isCacheDirty(invalidConfigFile, buildFolder, lockfiles))
515+
assertThat(
516+
ReactSettingsExtension.isCacheDirty(
517+
invalidConfigFile,
518+
buildFolder,
519+
lockfiles,
520+
tempFolder.root,
521+
),
522+
)
420523
.isTrue()
421524
}
422525

@@ -454,7 +557,14 @@ class ReactSettingsExtensionTest {
454557
.trimIndent(),
455558
)
456559

457-
assertThat(ReactSettingsExtension.isCacheDirty(invalidConfigFile, buildFolder, lockfiles))
560+
assertThat(
561+
ReactSettingsExtension.isCacheDirty(
562+
invalidConfigFile,
563+
buildFolder,
564+
lockfiles,
565+
tempFolder.root,
566+
),
567+
)
458568
.isTrue()
459569
}
460570

0 commit comments

Comments
 (0)