Skip to content

Commit 5a0cbef

Browse files
authored
Make single instance assertion work with Gradle Configuration Cache (#2453)
## Description Makes `assertNoMultipleInstances` task not break when [Gradle Configuration Cache](https://docs.gradle.org/current/userguide/configuration_cache.html#config_cache:intro) is enabled. Fixes #2449. ## Test plan Enable configuration cache by adding `org.gradle.unsafe.configuration-cache=true` in `gradle.properties` file and build the app twice. Do it once without this patch and once with it.
1 parent 8bbc597 commit 5a0cbef

File tree

3 files changed

+70
-31
lines changed

3 files changed

+70
-31
lines changed

android/build.gradle

Lines changed: 65 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import groovy.json.JsonSlurper
2-
import java.nio.file.Paths
2+
3+
import javax.inject.Inject
4+
import java.nio.file.Files
35

46
buildscript {
57
def kotlin_version = rootProject.ext.has('kotlinVersion') ? rootProject.ext.get('kotlinVersion') : project.properties['RNGH_kotlinVersion']
@@ -66,6 +68,14 @@ if (project == rootProject) {
6668
apply from: "spotless.gradle"
6769
}
6870

71+
def shouldAssertNoMultipleInstances() {
72+
if (rootProject.hasProperty("disableMultipleInstancesCheck")) {
73+
return rootProject.property("disableMultipleInstancesCheck") != "true"
74+
} else {
75+
return true
76+
}
77+
}
78+
6979
// Check whether Reanimated 2.3 or higher is installed alongside Gesture Handler
7080
def shouldUseCommonInterfaceFromReanimated() {
7181
def reanimated = rootProject.subprojects.find { it.name == 'react-native-reanimated' }
@@ -85,28 +95,6 @@ def reactNativeArchitectures() {
8595
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
8696
}
8797

88-
def shouldAssertNoMultipleInstances() {
89-
if (rootProject.hasProperty("disableMultipleInstancesCheck")) {
90-
return rootProject.property("disableMultipleInstancesCheck") != "true"
91-
} else {
92-
return true
93-
}
94-
}
95-
96-
def noMultipleInstancesAssertion() {
97-
Set<File> files = fileTree(rootDir.parent) {
98-
include "node_modules/**/react-native-gesture-handler/package.json"
99-
exclude "**/.yarn/**"
100-
exclude "**/.pnpm/**"
101-
}.files
102-
103-
if (files.size() > 1) {
104-
String parsedLocation = files.stream().map({ File file -> "- " + file.toString().replace("/package.json", "") }).collect().join("\n")
105-
String exceptionMessage = "\n[Gesture Handler] Multiple instances of Gesture Handler were detected. Only one instance of react-native-gesture-handler can be installed in a project. You need to resolve the conflict manually. Check out the documentation: https://docs.swmansion.com/react-native-gesture-handler/docs/troubleshooting#multiple-instances-of-gesture-handler-were-detected \n\nConflict between: \n" + parsedLocation + "\n";
106-
throw new Exception(exceptionMessage);
107-
}
108-
}
109-
11098
def REACT_NATIVE_DIR = resolveReactNativeDirectory()
11199

112100
def reactProperties = new Properties()
@@ -115,17 +103,65 @@ file("$REACT_NATIVE_DIR/ReactAndroid/gradle.properties").withInputStream { react
115103
def REACT_NATIVE_VERSION = reactProperties.getProperty("VERSION_NAME")
116104
def REACT_NATIVE_MINOR_VERSION = REACT_NATIVE_VERSION.startsWith("0.0.0-") ? 1000 : REACT_NATIVE_VERSION.split("\\.")[1].toInteger()
117105

118-
def assertionTask = task assertNoMultipleInstances {
119-
onlyIf { shouldAssertNoMultipleInstances() }
120-
doFirst {
121-
noMultipleInstancesAssertion()
106+
107+
abstract class NoMultipleInstancesAssertionTask extends DefaultTask {
108+
@Inject abstract ObjectFactory getObjectFactory()
109+
110+
@Input abstract Property<File> getProjectDirFile()
111+
@Input abstract Property<File> getRootDirFile()
112+
@Input abstract Property<Boolean> getShouldCheck()
113+
114+
def findGestureHandlerInstancesForPath(String path) {
115+
return objectFactory.fileTree().from(path)
116+
.include("**/react-native-gesture-handler/package.json")
117+
.exclude("**/.yarn/**")
118+
.exclude({ Files.isSymbolicLink(it.getFile().toPath()) })
119+
.findAll()
120+
}
121+
122+
@TaskAction
123+
def check() {
124+
if (shouldCheck.get()) {
125+
// Assert there are no multiple installations of Gesture Handler
126+
Set<File> files
127+
128+
if (projectDirFile.get().parent.contains(rootDirFile.get().parent)) {
129+
// standard app
130+
files = findGestureHandlerInstancesForPath(rootDirFile.get().parent + "/node_modules")
131+
} else {
132+
// monorepo
133+
files = findGestureHandlerInstancesForPath(rootDirFile.get().parent + "/node_modules")
134+
files.addAll(
135+
findGestureHandlerInstancesForPath(projectDirFile.get().parentFile.parent)
136+
)
137+
}
138+
139+
if (files.size() > 1) {
140+
String parsedLocation = files.stream().map({
141+
File file -> "- " + file.toString().replace("/package.json", "")
142+
}).collect().join("\n")
143+
String exceptionMessage = "\n[react-native-gesture-handler] Multiple versions of Gesture Handler " +
144+
"were detected. Only one instance of react-native-gesture-handler can be installed in a " +
145+
"project. You need to resolve the conflict manually. Check out the documentation: " +
146+
"https://docs.swmansion.com/react-native-gesture-handler/docs/troubleshooting" +
147+
"#multiple-instances-of-gesture-handler-were-detected \n\nConflict between: \n" +
148+
parsedLocation + "\n"
149+
throw new GradleException(exceptionMessage)
150+
}
151+
}
122152
}
123153
}
124154

125-
tasks.preBuild {
126-
dependsOn assertionTask
155+
tasks.register('assertNoMultipleInstances', NoMultipleInstancesAssertionTask) {
156+
shouldCheck = shouldAssertNoMultipleInstances()
157+
rootDirFile = rootDir
158+
projectDirFile = projectDir
127159
}
128160

161+
tasks.preBuild {
162+
dependsOn assertNoMultipleInstances
163+
}
164+
129165
repositories {
130166
mavenCentral()
131167
}

docs/docs/troubleshooting.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ This error usually happens when in your project there exists more than one insta
4141
You can check which libraries are using Gesture Handler, for example, with the command:
4242

4343
```bash
44-
npm why react-native-gesture-handler
44+
npm ls react-native-gesture-handler
45+
yarn why react-native-gesture-handler
4546
```
4647

4748
If you use `yarn` you should add [`resolution` property](https://classic.yarnpkg.com/lang/en/docs/selective-version-resolutions/).

example/android/gradle.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,6 @@ newArchEnabled=false
4040

4141
# Use this property to enable or disable the Hermes JS engine.
4242
# If set to false, you will be using JSC instead.
43-
hermesEnabled=true
43+
hermesEnabled=true
44+
45+
disableMultipleInstancesCheck=false

0 commit comments

Comments
 (0)