checkstyle + gradle + git pre-commit 实现代码提交前对代码规范的检查

我们的目的是想在代码commit之前去做这个检查,把不符合规范的代码标记出来,直到修改完成之后才允许提交。脚本涉及到几个重要的文件:1.pre-commit, 这个是git的一个hook文件,可以帮助我们在commit前去做一些事情,比如,调用我们第二步定义的checkstyle。2.checkstyle.gradle,这里面主要包含gradle的一个task,通过依赖checkstyle插件,然后定义我们自己的checkstyle task 去获取commit前的一些待提交文件,再运用我们定义的规则去做检查。3.checkstyle.xml文件,这个就是定义规则的文件,参考了google编码规范和华为编码规范。4.suppressions.xml,这个是过滤选项,也即是可以排除某些指定文件不受代码规范的检查,比如协议文件。

由于现在AndroidStudio已经支持了checkstyle插件,所以我们只要在.gradle文件里面引用就可以了。(我们这里采用的是checkstyle 6.5)

1.通常,我们会包装自己的checkstyle脚本,将其命名为checkstyle.gradle。代码如下:

apply plugin: 'checkstyle'

dependencies {

    //也可依赖于生成的jar包,以后再说
    //compile fileTree(dir: 'libs', include: ['*.jar'])
    //checkstyle files('../custom-checkstyle/custom-checkstyle.jar')

    //checkstyle task 依赖 custom-checkstyle module, custom-checkstyle moudle有自定义的Check
    checkstyle project(':custom-checkstyle')

    // for using compiled version
    //checkstyle 'com.puppycrawl.tools:checkstyle:6.5'

}

def reportsDir = "${
 project.buildDir}/reports"

checkstyle {
    //工具版本
    toolVersion '6.5'
    //配置文件路径
    configFile file("${
 project.rootDir}/checkstyle.xml")
    //filter路径
    configProperties.checkstyleSuppressionsPath = file("${
 project.rootDir}/suppressions.xml").absolutePath
}

task checkstyle(type: Checkstyle, group: 'verification') {

    try {
 //try一下,即使发生异常也不影响正常编译

        def isCheck = true //是否打开代码规范检查的开关
        def isCommit = project.hasProperty('checkCommit') //是否是提交前检查
        if (isCheck) {
            if (isCommit) {
                //检测代码路径
                 //source project.rootDir //--- 检查项目中所有的文件, 比较慢, 下面分模块检查, 主要是src下面的java文件
                 source 'xxx/src'
                source 'lib-xxx/src'
                source 'src' //submodules的检查

                //排除项
                 exclude '**/gen/**'
                exclude '**/test/**'
                exclude '**/res/**'
                exclude '**/androidTest/**'
                exclude '**/R.java'
                exclude '**/BuildConfig.java'
                
                //判断是否是git pre-commit hook触发的checkstyle
                //如果是,只检测要提交的java文件,否则检测路径下的所有java文件
                if (project.hasProperty('checkCommit') && project.property("checkCommit")) {
                    def ft = filterCommitter(getChangeFiles())
                    def includeList = new ArrayList<String>()
                    for (int i = 0; i < ft.size(); i++) {
                        String spliter = ft.getAt(i)
                        String[] spliterlist = spliter.split("/")
                        String fileName = spliterlist[spliterlist.length - 1]
                        includeList.add("**/" + fileName)
                    }
                    if (includeList.size() == 0) {
                        exclude '**/*.java'
                    } else {
                        println("includeList==" + includeList)
                        include includeList
                    }
                } else {
                    include '**/*.java'
                }
                classpath = files()

                reports { // 支持htmlxml两种报告形式,可以任选其一(html更具有可读性)
                    xml.enabled = false
                    html.enabled = true
                    xml {
                        destination file("$reportsDir/checkstyle/checkstyle.xml")
                    }
                    html {
                        destination file("$reportsDir/checkstyle/checkstyle.html")
                    }
                }
            } else { //如果不是提交触发的,也就是对项目进行构建,那么需要对pre-commit文件进行copy
                def forceCopy = false //如有需要,可以强制去更新客户端的pre-commit文件
                try {
                    copyPreCommitFile(forceCopy)
                    //copySubmodulesPreCommitFile(forceCopy)
                } catch (Exception e) {
                    println(e)
                }
            }
        }

    }catch (Exception e){
        println("checkstyle catch an exception.")
        e.printStackTrace()
    }
}

//src是一个文件路径,target是一个目录路径
def copyFile(boolean forceUpdate, String src, String target){
    def fileName = "pre-commit"
    def targetFile = file(target + "/" + fileName)

    if(targetFile.exists() && targetFile.isFile() && !forceUpdate){ //目标文件存在且没有强制更新,不需要copy操作
        println(targetFile.absolutePath + " exist.")
    }else {
        //targetFile.delete()
        def srcFile = file(src)
        if (srcFile.isFile()) {
            copy {
                from srcFile
                into target
            }
        }
    }

    //targetFile = file(target + "/" + fileName)
    if(targetFile.isFile()) {
        if (!targetFile.canExecute()) {
            targetFile.setExecutable(true)
        }
        if (!targetFile.canWrite()) {
            targetFile.setWritable(true)
        }
    }
}

//把根目录下的pre-commit文件复制到.git-->hooks目录
def copyPreCommitFile(boolean forceUpdate){

    def src = "${
 project.rootDir}/pre-commit"
    def target = "${
 project.rootDir}/.git/hooks"
    copyFile(forceUpdate, src, target)

    println("copyPreCommitFile")
}

//submodules目录下的pre-commit文件复制到.git-->modules-->submodules-->XXXmoudles-->hooks 目录
def copySubmodulesPreCommitFile(boolean forceUpdate){

    def src = "${
 project.rootDir}/submodules/pre-commit"
    def submodulesDir = "${
 project.rootDir}/.git/modules/submodules"
    File file = new File(submodulesDir)
    File[] fileList = file.listFiles()
    if(fileList != null && fileList.length > 0) {
        def size = fileList.length
        for (int i = 0; i < size; i++) {
            if (fileList[i].isDirectory()) {
                //target = "${project.rootDir}/.git/modules/submodules/XXX/hooks"
                def target = submodulesDir + "/" + fileList[i].getName() + "/hooks"
                copyFile(forceUpdate, src, target)
            }
        }
    }

    println("copySubmodulesPreCommitFile")
}

//过滤java文件
def filterCommitter(String gitstatusinfo) {
    ArrayList<String> filterList = new ArrayList<String>()
    String[] lines = gitstatusinfo.split("\\n")
    for (String line : lines) {
        if (!line.startsWith("D ") && line.contains(".java") ) {
            String[] spliters = line.trim().split(" ")
            for (String str : spliters) {
                if (str.contains(".java")) {
                    filte
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值