Skip to content

Commit

Permalink
Make single instance assertion work with Gradle Configuration Cache (#…
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
j-piasecki committed Apr 26, 2023
1 parent 8bbc597 commit 5a0cbef
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 31 deletions.
94 changes: 65 additions & 29 deletions android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import groovy.json.JsonSlurper
import java.nio.file.Paths

import javax.inject.Inject
import java.nio.file.Files

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

def shouldAssertNoMultipleInstances() {
if (rootProject.hasProperty("disableMultipleInstancesCheck")) {
return rootProject.property("disableMultipleInstancesCheck") != "true"
} else {
return true
}
}

// Check whether Reanimated 2.3 or higher is installed alongside Gesture Handler
def shouldUseCommonInterfaceFromReanimated() {
def reanimated = rootProject.subprojects.find { it.name == 'react-native-reanimated' }
Expand All @@ -85,28 +95,6 @@ def reactNativeArchitectures() {
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
}

def shouldAssertNoMultipleInstances() {
if (rootProject.hasProperty("disableMultipleInstancesCheck")) {
return rootProject.property("disableMultipleInstancesCheck") != "true"
} else {
return true
}
}

def noMultipleInstancesAssertion() {
Set<File> files = fileTree(rootDir.parent) {
include "node_modules/**/react-native-gesture-handler/package.json"
exclude "**/.yarn/**"
exclude "**/.pnpm/**"
}.files

if (files.size() > 1) {
String parsedLocation = files.stream().map({ File file -> "- " + file.toString().replace("/package.json", "") }).collect().join("\n")
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";
throw new Exception(exceptionMessage);
}
}

def REACT_NATIVE_DIR = resolveReactNativeDirectory()

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

def assertionTask = task assertNoMultipleInstances {
onlyIf { shouldAssertNoMultipleInstances() }
doFirst {
noMultipleInstancesAssertion()

abstract class NoMultipleInstancesAssertionTask extends DefaultTask {
@Inject abstract ObjectFactory getObjectFactory()

@Input abstract Property<File> getProjectDirFile()
@Input abstract Property<File> getRootDirFile()
@Input abstract Property<Boolean> getShouldCheck()

def findGestureHandlerInstancesForPath(String path) {
return objectFactory.fileTree().from(path)
.include("**/react-native-gesture-handler/package.json")
.exclude("**/.yarn/**")
.exclude({ Files.isSymbolicLink(it.getFile().toPath()) })
.findAll()
}

@TaskAction
def check() {
if (shouldCheck.get()) {
// Assert there are no multiple installations of Gesture Handler
Set<File> files

if (projectDirFile.get().parent.contains(rootDirFile.get().parent)) {
// standard app
files = findGestureHandlerInstancesForPath(rootDirFile.get().parent + "/node_modules")
} else {
// monorepo
files = findGestureHandlerInstancesForPath(rootDirFile.get().parent + "/node_modules")
files.addAll(
findGestureHandlerInstancesForPath(projectDirFile.get().parentFile.parent)
)
}

if (files.size() > 1) {
String parsedLocation = files.stream().map({
File file -> "- " + file.toString().replace("/package.json", "")
}).collect().join("\n")
String exceptionMessage = "\n[react-native-gesture-handler] Multiple versions 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"
throw new GradleException(exceptionMessage)
}
}
}
}

tasks.preBuild {
dependsOn assertionTask
tasks.register('assertNoMultipleInstances', NoMultipleInstancesAssertionTask) {
shouldCheck = shouldAssertNoMultipleInstances()
rootDirFile = rootDir
projectDirFile = projectDir
}

tasks.preBuild {
dependsOn assertNoMultipleInstances
}

repositories {
mavenCentral()
}
Expand Down
3 changes: 2 additions & 1 deletion docs/docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ This error usually happens when in your project there exists more than one insta
You can check which libraries are using Gesture Handler, for example, with the command:

```bash
npm why react-native-gesture-handler
npm ls react-native-gesture-handler
yarn why react-native-gesture-handler
```

If you use `yarn` you should add [`resolution` property](https://classic.yarnpkg.com/lang/en/docs/selective-version-resolutions/).
Expand Down
4 changes: 3 additions & 1 deletion example/android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,6 @@ newArchEnabled=false

# Use this property to enable or disable the Hermes JS engine.
# If set to false, you will be using JSC instead.
hermesEnabled=true
hermesEnabled=true

disableMultipleInstancesCheck=false

0 comments on commit 5a0cbef

Please sign in to comment.