模块化工程本地和远程仓库代码动态切换脚本

478 阅读1分钟

我们知道,子模块要编译到主工程中,需要再主工程根目录下的settings.gradle文件中设置子模块的引用路径和模块名称。

下面的配置是引用主工程当前目录下demo目录下的模块。

include ':demo'

下面是引用其他目录下的模块。

include 'demo'
project(':demo').projectDir =file('../zpw/demo')

要实现主工程替换本地和远程仓库代码的功能,可以先增加一个开关depend用于决定使用哪一端的代码,然后还需要设置项目名,项目地址,在主工程中对应的模块名。

{
  "depend": true,
  "project": "demo",
  "projectDir": "D:\Android\workspace\demo",
  "module": "com.zpw.demo:demo"
}

然后在settings.gradle中运行下列代码。

apply from: AUTO_INCLUDE_URL
evaluate(autoIncludeScript)

我们可以将下面代码以文件的方式保存在maven仓库中。

ext {
    autoIncludeScript = '''
        import groovy.json.JsonSlurper

        def dependFile = new File(gradle.rootDir, 'dependency.json')
        if (!dependFile.exists()) {
            println "file dependency.json missing, generating..."
            dependFile <<
                    """
                    [
                      {
                        "depend": false,
                        "//depend": "true: impmlementation project,false: implementation 'group:artifacts:version'",
                        "project": "",
                        "//project": "project name, e.g. umeng, business_weex",
                        "projectDir": "",
                        "//projectDir": "absolute path of project, e.g. D:\\\\MyData\\\\AndroidStudioProjects\\\\component-service\\\\umeng",
                        "module": "",
                        "//module": "group:artifacts of module, e.g. com.midea.service:umeng"
                      },
                      {
                        "depend": false,
                        "project": "",
                        "projectDir": "",
                        "module": ""
                      }
                    ]
                    """.stripIndent()
        } else {
            println "file dependency.json exist"
        }
        
        def gitignore = new File(gradle.rootDir, '.gitignore')
        boolean needAdd = true
        if (gitignore.exists()) {
            gitignore.eachLine {
                if (it.contains('dependency.json')) {
                    println("dependency.json has already added in .gitignore")
                    needAdd = false
                }
            }
            if (needAdd) {
                println "add dependency.json into .gitignore"
                gitignore << "\ndependency.json"
            }
        }
        
        if (!dependFile.canRead()) {
            println "file dependency.json is unreadable"
            return
        }
        try {
            def dependJson = new JsonSlurper().parseText(dependFile.text)
            dependJson.forEach {
                println "project=$it.project, depend=$it.depend"
                if (it.depend && it.project != null && it.project.length() > 0
                        && it.projectDir != null && it.projectDir.length() > 0
                        && it.module != null && it.module.length() > 0) {
                    println "include $it.project"
                    gradle.include ":$it.project"
                    gradle.project(":$it.project").projectDir = new File(it.projectDir)
                }
            }
        } catch (e) {
            println "autoInclude exception: $e"
        }

    '''
}

最后要切换的时候只需要在AS中同步代码皆可拉取对应段的代码。

拉取到代码之后,因为我们的主工程的build.gradle中默认依赖了远程仓库的代码。

dependencies {
    implementation "com.zpw.demo:demo"
}

我们需要在编译的过程中替换原来的依赖,gradle提供了替换依赖的工具,我们可以在编译的过程中进行替换,编写以下插件。

import groovy.json.JsonSlurper
import org.gradle.api.Plugin
import org.gradle.api.Project

class DependPlugin implements Plugin<Project> {

    static final String TAG = "#DependPlugin"

    @Override
    void apply(Project project) {

        def file = new File("$project.rootDir/dependency.json")
        if (!file.exists()) {
            println "$TAG: file dependency.json missing"
            return
        }
        if (!file.canRead()) {
            println "$TAG: file dependency.json is unreadable"
            return
        }
        try {
            def json = new JsonSlurper().parseText(file.text)

            project.allprojects { p ->
                p.afterEvaluate {
                    json.forEach {
                        println "$TAG: configProject=$p, project=$it.project, depend=$it.depend"
                        if (it.project != null && it.project.length() > 0
                                && it.projectDir != null && it.projectDir.length() > 0
                                && it.module != null && it.module.length() > 0) {
                            if (it.depend) {
                                println "$TAG: convert module to project"
                                convert(p, it.module, it.project)
                            }
                        }
                    }
                }
            }
        } catch (e) {
            println "$TAG: execute exception: $e"
        }
    }

    private void convert(Project project, String moduleName, String projectName) {
        project.configurations.all {
            resolutionStrategy {
                dependencySubstitution { ds ->
                    substitute module(moduleName) with ds.project(":$projectName")
                }
            }
        }
    }

}

然后再壳工程的build.gradle文件中引入并执行。

classpath "com.zpw.demo.depend:depend-plugin:0.0.1-SNAPSHOT"
apply plugin: 'plugin.depend'