-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
167 additions
and
102 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
node_modules | ||
.gradle |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,126 +1,190 @@ | ||
import groovy.json.JsonSlurper | ||
|
||
def doesUnimoduleSupportPlatform(Map unimoduleJson, String platform) { | ||
def platforms = unimoduleJson.platforms | ||
return platforms instanceof List && platforms.contains(platform) | ||
import java.util.regex.Pattern | ||
|
||
class Unimodule { | ||
String name | ||
List platforms | ||
List targets | ||
List androidPackages | ||
String directory | ||
String version | ||
String androidSubdirectory | ||
|
||
boolean supportPlatform(String platform) { | ||
return platforms instanceof List && platforms.contains(platform) | ||
} | ||
|
||
boolean supportTarget(String target) { | ||
return targets.size() == 0 || targets.contains(target) | ||
} | ||
} | ||
|
||
def doesUnimoduleSupportTarget(Map unimoduleJson, String target) { | ||
def targets = unimoduleJson.targets | ||
return !targets || targets.contains(target) | ||
def findDefaultBasePackage(String packageDir) { | ||
def paths = new FileNameFinder().getFileNames(packageDir, "android/src/**/*Package.java", "") | ||
if (paths.size != 1) { | ||
return [] | ||
} | ||
def javaFile = new File(paths[0]) | ||
def javaFileReader = new BufferedReader(new FileReader(javaFile)) | ||
def javaFileContent = javaFileReader.readLine() | ||
def match = javaFileContent =~ /^package ([0-9a-zA-Z.]*);$/ | ||
if (match.size() == 1 && match[0].size() == 2) { | ||
def pkg = match[0][1] | ||
def className = javaFile.getName().split(Pattern.quote("."))[0] | ||
return ["$pkg.$className"] | ||
} | ||
javaFileReader.close() | ||
return [] | ||
} | ||
|
||
def findUnimodules(String target, List modulesToExclude, List modulesPaths) { | ||
def unimodules = [:] | ||
def unimodulesDuplicates = [] | ||
|
||
for (modulesPath in modulesPaths) { | ||
def baseDir = new File(rootProject.getBuildFile(), modulesPath).toString() | ||
def moduleConfigPaths = new FileNameFinder().getFileNames(baseDir, '**/unimodule.json', '') | ||
|
||
for (moduleConfigPath in moduleConfigPaths) { | ||
def unimoduleConfig = new File(moduleConfigPath) | ||
def unimoduleJson = new JsonSlurper().parseText(unimoduleConfig.text) | ||
def directory = unimoduleConfig.getParent() | ||
|
||
if (doesUnimoduleSupportPlatform(unimoduleJson, 'android') && doesUnimoduleSupportTarget(unimoduleJson, target)) { | ||
def packageJsonFile = new File(directory, 'package.json') | ||
def packageJson = new JsonSlurper().parseText(packageJsonFile.text) | ||
def unimoduleName = unimoduleJson.name ?: packageJson.name | ||
|
||
if (!modulesToExclude.contains(unimoduleName)) { | ||
def platformConfig = [subdirectory: 'android'] << unimoduleJson.get('android', [:]) | ||
def unimoduleVersion = packageJson.version | ||
|
||
if (unimodules[unimoduleName]) { | ||
unimodulesDuplicates.add(unimoduleName) | ||
} | ||
|
||
if (!unimodules[unimoduleName] || VersionNumber.parse(unimoduleVersion) >= VersionNumber.parse(unimodules[unimoduleName].version)) { | ||
unimodules[unimoduleName] = [ | ||
name: unimoduleJson.name, | ||
directory: directory, | ||
version: unimoduleVersion, | ||
config: platformConfig, | ||
] | ||
} | ||
def generateBasePackageList(List<Unimodule> unimodules) { | ||
def fileBuilder = new StringBuilder() | ||
fileBuilder.append("package host.exp.exponent.generated;\n\n") | ||
|
||
fileBuilder.append("import java.util.Arrays;\n") | ||
fileBuilder.append("import java.util.List;\n") | ||
fileBuilder.append("import org.unimodules.core.interfaces.Package;\n\n") | ||
|
||
fileBuilder.append("public class BasePackageList {\n") | ||
fileBuilder.append(" public List<Package> getPackageList() {\n") | ||
fileBuilder.append(" return Arrays.<Package>asList(\n") | ||
def isEmptyList = true | ||
for (module in unimodules) { | ||
for (pkg in module.androidPackages) { | ||
fileBuilder.append(" new $pkg(),\n") | ||
isEmptyList = false | ||
} | ||
} | ||
} | ||
} | ||
return [ | ||
unimodules: unimodules.collect { entry -> entry.value }, | ||
duplicates: unimodulesDuplicates.unique() | ||
] | ||
if (!isEmptyList) { | ||
fileBuilder.deleteCharAt(fileBuilder.length() - 2) // remove last comma in a list | ||
} | ||
fileBuilder.append(" );\n") | ||
fileBuilder.append(" }\n") | ||
fileBuilder.append("}\n") | ||
|
||
def javaFile = new File(rootProject.getProjectDir(), "app/src/main/java/host/exp/exponent/generated/BasePackageList.java") | ||
javaFile.createNewFile() | ||
def javaFileWriter = new BufferedWriter(new FileWriter(javaFile)) | ||
javaFileWriter.write(fileBuilder.toString()) | ||
javaFileWriter.close() | ||
} | ||
|
||
class Colors { | ||
static final String NORMAL = "\u001B[0m" | ||
static final String RED = "\u001B[31m" | ||
static final String GREEN = "\u001B[32m" | ||
static final String YELLOW = "\u001B[33m" | ||
static final String MAGENTA = "\u001B[35m" | ||
|
||
def findUnimodules(String target, List exclude, List modulesPaths) { | ||
|
||
def unimodules = [:] | ||
def unimodulesDuplicates = [] | ||
|
||
for (modulesPath in modulesPaths) { | ||
def baseDir = new File(rootProject.getBuildFile(), modulesPath).toString() | ||
def moduleConfigPaths = new FileNameFinder().getFileNames(baseDir, '**/unimodule.json', '') | ||
|
||
for (moduleConfigPath in moduleConfigPaths) { | ||
def unimoduleConfig = new File(moduleConfigPath) | ||
def unimoduleJson = new JsonSlurper().parseText(unimoduleConfig.text) | ||
def directory = unimoduleConfig.getParent() | ||
def packageJsonFile = new File(directory, 'package.json') | ||
def packageJson = new JsonSlurper().parseText(packageJsonFile.text) | ||
|
||
def unimodule = new Unimodule() | ||
unimodule.name = unimoduleJson.name ?: packageJson.name | ||
unimodule.directory = directory | ||
unimodule.version = packageJson.version ?: "UNVERSIONED" | ||
unimodule.androidSubdirectory = unimoduleJson.android?.subdirectory ?: "android" | ||
unimodule.platforms = unimoduleJson.platforms != null ? unimoduleJson.platforms : [] | ||
assert unimodule.platforms instanceof List | ||
unimodule.targets = unimoduleJson.targets != null ? unimoduleJson.targets : [] | ||
assert unimodule.targets instanceof List | ||
unimodule.androidPackages = unimoduleJson.android?.packages != null ? | ||
unimoduleJson.android.packages : findDefaultBasePackage(directory) | ||
assert unimodule.androidPackages instanceof List | ||
|
||
if (unimodule.supportPlatform('android') && unimodule.supportTarget(target)) { | ||
if (!exclude.contains(unimodule.name)) { | ||
if (unimodules[unimodule.name]) { | ||
unimodulesDuplicates.add(unimodule.name) | ||
} | ||
|
||
if (!unimodules[unimodule.name] || | ||
VersionNumber.parse(unimodule.version) >= VersionNumber.parse(unimodules[unimodule.name].version)) { | ||
unimodules[unimodule.name] = unimodule | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return [ | ||
unimodules: unimodules.collect { entry -> entry.value }, | ||
duplicates: unimodulesDuplicates.unique() | ||
] | ||
} | ||
|
||
ext.addUnimodulesDependencies = { Map customOptions = [:] -> | ||
if (!(new File(project.rootProject.projectDir.parentFile, 'package.json').exists())) { | ||
// There's no package.json | ||
throw new GradleException( | ||
"'addUnimodulesDependencies()' is being used in a project that doesn't seem to be a React Native project." | ||
) | ||
} | ||
|
||
def options = [ | ||
modulesPaths: ['../../node_modules'], | ||
configuration: 'implementation', | ||
target: 'react-native', | ||
exclude: [], | ||
] << customOptions | ||
|
||
def results = findUnimodules(options.target, options.exclude, options.modulesPaths) | ||
def unimodules = results.unimodules | ||
def duplicates = results.duplicates | ||
|
||
if (unimodules.size() > 0) { | ||
println() | ||
println Colors.YELLOW + 'Installing unimodules:' + Colors.NORMAL | ||
|
||
for (unimodule in unimodules) { | ||
println ' ' + Colors.GREEN + unimodule.name + Colors.YELLOW + '@' + Colors.RED + unimodule.version + Colors.NORMAL + ' from ' + Colors.MAGENTA + unimodule.directory + Colors.NORMAL | ||
class Colors { | ||
static final String NORMAL = "\u001B[0m" | ||
static final String RED = "\u001B[31m" | ||
static final String GREEN = "\u001B[32m" | ||
static final String YELLOW = "\u001B[33m" | ||
static final String MAGENTA = "\u001B[35m" | ||
} | ||
|
||
Object dependency = project.project(':' + unimodule.name) | ||
project.dependencies.add(options.configuration, dependency, null) | ||
ext.addUnimodulesDependencies = { Map customOptions = [:] -> | ||
if (!(new File(project.rootProject.projectDir.parentFile, 'package.json').exists())) { | ||
// There's no package.json | ||
throw new GradleException( | ||
"'addUnimodulesDependencies()' is being used in a project that doesn't seem to be a React Native project." | ||
) | ||
} | ||
|
||
if (duplicates.size() > 0) { | ||
println() | ||
println Colors.YELLOW + 'Found some duplicated unimodule packages. Installed the ones with the highest version number.' + Colors.NORMAL | ||
println Colors.YELLOW + 'Make sure following dependencies of your project are resolving to one specific version:' + Colors.NORMAL | ||
def options = [ | ||
modulesPaths : ['../../node_modules'], | ||
configuration: 'implementation', | ||
target : 'react-native', | ||
exclude : [], | ||
] << customOptions | ||
|
||
def results = findUnimodules(options.target, options.exclude, options.modulesPaths) | ||
def unimodules = results.unimodules | ||
def duplicates = results.duplicates | ||
generateBasePackageList(unimodules) | ||
|
||
if (unimodules.size() > 0) { | ||
println() | ||
println Colors.YELLOW + 'Installing unimodules:' + Colors.NORMAL | ||
for (unimodule in unimodules) { | ||
println ' ' + Colors.GREEN + unimodule.name + Colors.YELLOW + '@' + Colors.RED + unimodule.version + Colors.NORMAL + ' from ' + Colors.MAGENTA + unimodule.directory + Colors.NORMAL | ||
|
||
Object dependency = project.project(':' + unimodule.name) | ||
project.dependencies.add(options.configuration, dependency, null) | ||
} | ||
|
||
if (duplicates.size() > 0) { | ||
println() | ||
println Colors.YELLOW + 'Found some duplicated unimodule packages. Installed the ones with the highest version number.' + Colors.NORMAL | ||
println Colors.YELLOW + 'Make sure following dependencies of your project are resolving to one specific version:' + Colors.NORMAL | ||
|
||
println ' ' + duplicates | ||
.collect { unimoduleName -> Colors.GREEN + unimoduleName + Colors.NORMAL } | ||
.join(', ') | ||
println ' ' + duplicates | ||
.collect { unimoduleName -> Colors.GREEN + unimoduleName + Colors.NORMAL } | ||
.join(', ') | ||
} | ||
} else { | ||
println() | ||
println Colors.YELLOW + "No unimodules found. Are you sure you've installed JS dependencies?" + Colors.NORMAL | ||
} | ||
} else { | ||
println() | ||
println Colors.YELLOW + "No unimodules found. Are you sure you've installed JS dependencies?" + Colors.NORMAL | ||
} | ||
} | ||
|
||
ext.includeUnimodulesProjects = { Map customOptions = [:] -> | ||
def options = [ | ||
modulesPaths: ['../../node_modules'], | ||
target: 'react-native', | ||
exclude: [], | ||
] << customOptions | ||
|
||
def unimodules = findUnimodules(options.target, options.exclude, options.modulesPaths).unimodules | ||
def options = [ | ||
modulesPaths: ['../../node_modules'], | ||
target : 'react-native', | ||
exclude : [], | ||
] << customOptions | ||
|
||
for (unimodule in unimodules) { | ||
def config = unimodule.config | ||
def subdirectory = config.subdirectory | ||
def unimodules = findUnimodules(options.target, options.exclude, options.modulesPaths).unimodules | ||
|
||
include ":${unimodule.name}" | ||
project(":${unimodule.name}").projectDir = new File(unimodule.directory, subdirectory) | ||
} | ||
for (unimodule in unimodules) { | ||
include ":${unimodule.name}" | ||
project(":${unimodule.name}").projectDir = new File(unimodule.directory, unimodule.androidSubdirectory) | ||
} | ||
} |