Skip to content

Commit

Permalink
generate android pacakge list
Browse files Browse the repository at this point in the history
  • Loading branch information
wkozyra95 committed Apr 10, 2019
1 parent 4b2257e commit a93633a
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 102 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules
.gradle
268 changes: 166 additions & 102 deletions gradle.groovy
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)
}
}

0 comments on commit a93633a

Please sign in to comment.