Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

generate android pacakge list #28

Merged
merged 7 commits into from
Apr 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules
.gradle
235 changes: 180 additions & 55 deletions gradle.groovy
Original file line number Diff line number Diff line change
@@ -1,16 +1,116 @@
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 androidGroup
String androidSubdirectory

boolean supportsPlatform(String platform) {
return platforms instanceof List && platforms.contains(platform)
}

boolean supportsTarget(String target) {
return targets.size() == 0 || targets.contains(target)
}
}

def readPackageFromJavaFile(String file) {
def javaFile = new File(file)
def javaFileReader = new BufferedReader(new FileReader(javaFile))
def javaFileContent = ""
while (javaFileContent.trim() == "") {
javaFileContent = javaFileReader.readLine()
}
javaFileReader.close()
def match = javaFileContent =~ /^package ([0-9a-zA-Z._]*);$/
if (match.size() == 1 && match[0].size() == 2) {
return match[0][1]
}

throw new GradleException("File $file does not include package declaration")
}

def readFromBuildGradle(String file) {
def gradleFile = new File(file)
if (!gradleFile.exists()) {
return [:]
}
def fileReader = new BufferedReader(new FileReader(gradleFile))
def result = [:]
for (def line = fileReader.readLine(); line != null; line = fileReader.readLine()) {
def versionMatch = line.trim() =~ /^version ?= ?'([0-9]+.[0-9]+.[0-9]+)'$/
def groupMatch = line.trim() =~ /^group ?= ?'([a-zA-Z]+.[a-zA-Z]+.[a-zA-Z]+)'$/
if (versionMatch.size() == 1 && versionMatch[0].size() == 2) {
result.version = versionMatch[0][1]
}
if (groupMatch.size() == 1 && groupMatch[0].size() == 2) {
result.group = groupMatch[0][1]
}
}
fileReader.close()
return result
}

def findDefaultBasePackage(String packageDir) {
def paths = new FileNameFinder().getFileNames(packageDir, "android/src/**/*Package.java", "")
if (paths.size != 1) {
return []
}
def packageName = readPackageFromJavaFile(paths[0])
def className = new File(paths[0]).getName().split(Pattern.quote("."))[0]
return ["$packageName.$className"]
}

def doesUnimoduleSupportTarget(Map unimoduleJson, String target) {
def targets = unimoduleJson.targets
return !targets || targets.contains(target)
def generateBasePackageList(List<Unimodule> unimodules) {
def findMainApp = new FileNameFinder().getFileNames(rootProject.getProjectDir().getPath(), '**/MainApplication.java', '')
if (findMainApp.size() != 1) {
throw new GradleException("You need to have MainApplication.java in your project")
}
def mainAppDirectory = new File(findMainApp[0]).parentFile
def packageName = readPackageFromJavaFile(findMainApp[0])

def fileBuilder = new StringBuilder()
fileBuilder.append("package ${packageName}.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
}
}
if (!isEmptyList) {
fileBuilder.deleteCharAt(fileBuilder.length() - 2) // remove last comma in a list
}
fileBuilder.append(" );\n")
fileBuilder.append(" }\n")
fileBuilder.append("}\n")


new File(mainAppDirectory, "generated").mkdirs()
def javaFile = new File(mainAppDirectory, "generated/BasePackageList.java")
javaFile.createNewFile()
def javaFileWriter = new BufferedWriter(new FileWriter(javaFile))
javaFileWriter.write(fileBuilder.toString())
javaFileWriter.close()
}

def findUnimodules(String target, List modulesToExclude, List modulesPaths) {

def findUnimodules(String target, List exclude, List modulesPaths) {
def unimodules = [:]
def unimodulesDuplicates = []

Expand All @@ -22,74 +122,72 @@ def findUnimodules(String target, List modulesToExclude, List modulesPaths) {
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)
def buildGradle = readFromBuildGradle(new File(directory, "android/build.gradle").toString())
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 = buildGradle.version ?: packageJson.version ?: "UNVERSIONED"
unimodule.androidGroup = buildGradle.group ?: "org.unimodules"
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.supportsPlatform('android') && unimodule.supportsTarget(target)) {
if (!exclude.contains(unimodule.name)) {
if (unimodules[unimodule.name]) {
unimodulesDuplicates.add(unimodule.name)
}

if (!unimodules[unimoduleName] || VersionNumber.parse(unimoduleVersion) >= VersionNumber.parse(unimodules[unimoduleName].version)) {
unimodules[unimoduleName] = [
name: unimoduleJson.name,
directory: directory,
version: unimoduleVersion,
config: platformConfig,
]
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()
unimodules: unimodules.collect { entry -> entry.value },
duplicates: unimodulesDuplicates.unique()
]
}


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 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"
}

ext.addUnimodulesDependencies = { Map customOptions = [:] ->
def addUnimodulesDependencies(String target, List exclude, List modulesPaths, Closure<Boolean> addUnimodule) {
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."
"'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 results = findUnimodules(target, exclude, 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)
addUnimodule(unimodule)
}

if (duplicates.size() > 0) {
Expand All @@ -98,29 +196,56 @@ ext.addUnimodulesDependencies = { Map customOptions = [:] ->
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(', ')
.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
}
}

ext.addUnimodulesDependencies = { Map customOptions = [:] ->
def options = [
modulesPaths : ['../../node_modules'],
configuration: 'implementation',
target : 'react-native',
exclude : [],
] << customOptions

addUnimodulesDependencies(options.target, options.exclude, options.modulesPaths, {unimodule ->
Object dependency = project.project(':' + unimodule.name)
project.dependencies.add(options.configuration, dependency)
})
}

ext.addMavenUnimodulesDependencies = { Map customOptions = [:] ->
def options = [
modulesPaths : ['../../node_modules'],
configuration: 'implementation',
target : 'react-native',
exclude : [],
] << customOptions

addUnimodulesDependencies(options.target, options.exclude, options.modulesPaths, {unimodule ->
project.dependencies.add(
options.configuration,
"${unimodule.androidGroup}:${unimodule.name}:${unimodule.version}"
)
})
}

ext.includeUnimodulesProjects = { Map customOptions = [:] ->
def options = [
modulesPaths: ['../../node_modules'],
target: 'react-native',
exclude: [],
modulesPaths: ['../../node_modules'],
target : 'react-native',
exclude : [],
] << customOptions

def unimodules = findUnimodules(options.target, options.exclude, options.modulesPaths).unimodules

for (unimodule in unimodules) {
def config = unimodule.config
def subdirectory = config.subdirectory

include ":${unimodule.name}"
project(":${unimodule.name}").projectDir = new File(unimodule.directory, subdirectory)
project(":${unimodule.name}").projectDir = new File(unimodule.directory, unimodule.androidSubdirectory)
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"expo-constants": "~4.0.0",
"expo-file-system": "~4.0.0",
"expo-permissions": "~4.0.0",
"expo-app-loader-provider": "~4.0.0",
"unimodules-barcode-scanner-interface": "~1.0.0",
"unimodules-camera-interface": "~1.0.0",
"unimodules-constants-interface": "~1.0.0",
Expand Down