系列文章目录

Android打造专有hook,让不标准的代码摧残在萌芽之中

在第一篇的概述中,关于本系列文章,我大约预估了一下,需求四篇文章来进行解说,根本上便是,第一篇了解用法和实践当中的作用,第二篇和第三篇进入实战,终究一篇收尾及市场发布,让别人运用,尽量做到,细致入微,毫无保留的共享给咱们,期望能给咱们在标准的检测上带来一丝帮助,想了解终究标准检测功用的朋友,能够看第一篇的内容,里边有终究的完成作用,今天,咱们共享第二篇。

本篇文章内容大约分为以下几个模块

1、Git Hook介绍

2、根本环境建立

3、创立动态装备文件

4、代码初始化

一、Git Hook介绍

由第一篇的相关常识,咱们能够知道,当下所做的这个检测功用,是在Git提交之前进行检测,也便是说,在Git触发commit时,就需求进行阻拦,而在实践的运用当中,Git现已向咱们供给了Hook,也便是钩子,便于咱们进行指令的操作,关于Hook呢,分为两种,一种是客户端Hooks,比方提交和兼并这样的操作所调用,一种是服务端Hooks,作用于接纳被推送的提交这样的联网操作,而现在咱们要完成的是客户端Hooks。

关于Git的Hooks,其实很常见,方位存在于 /.git/hooks 目录下,都是一些 shell 脚本,然后在对应的钩子中履行这些脚本就行了,比方下图中,这是一个还没有装备 Git Hooks 的仓库,默许会有许多.sample完毕的文件,这些都是示例文件,比方咱们常见的,commit,push等。

Android打造专有hook第二篇,走进规范第一步

Git 支持的钩子类型有许多,比方,post-update,pre-commit等,我简略的举几个常见的,列个表格,咱们感兴趣的能够作为参考。

Git hook 概述
pre-commit 钩子在键入提交信息前运转。它用于查看行将提交的快照,例如,查看是否有所遗失,保证测验运转,以及核查代码。假如该钩子以非零值退出,Git 将抛弃此次提交,不过你能够用 git commit –no-verify 来绕过这个环节。你能够运用该钩子,来查看代码风格是否共同(运转类似 lint 的程序)、跟随空白字符是否存在(自带的钩子便是这么做的),或新办法的文档是否恰当。
pre-push 钩子会在 git push 运转期间, 更新了长途引证但没有传送目标时被调用。它承受长途分支的姓名和方位作为参数,一起从标准输入中读取一系列待更新的引证。你能够在推送开端之前,用它验证对引证的更新操作(一个非零的退出码将停止推送进程)。
post-update 仅在一切的ref被push之后履行一次。它与post-receive很像,可是不接纳旧值与新值。主要用于告诉。每个被push的repo都会生成一个参数,参数内容是ref的称号。
applypatch-msg 它接纳单个参数:包括请求兼并信息的临时文件的姓名。假如脚本回来非零值,Git 将抛弃该补丁。你能够用该脚原本保证提交信息符合格局,或直接用脚本批改格局过错。
commit-msg 钩子在发动提交信息修改器之前,默许信息被创立之后运转。它答应你修改提交者所看到的默许信息。该钩子接纳一些选项:存有当时提交信息的文件的路径、提交类型和修补提交的提交的 SHA-1 校验。它对一般的提交来说并没有什么用;然而对那些会自动产生默许信息的提交,如提交信息模板、兼并提交、紧缩提交和修订提交等非常有用。你能够结合提交模板来运用它,动态地插入信息。
pre-applypatch 实践上的调用时机是运用补丁之后、改变commit之前。假如以非0的状况退出,会导致改变成为uncommitted状况。可用于在实践进行commit之前查看代码树的状况或用它在提交前查看快照。你能够用这个脚本运转测验或查看工作区。假如有什么遗失,或测验未能经过,脚本会以非零值退出,中断 git am 的运转,这样补丁就不会被提交。

而咱们本次所运用的便是经过pre-commit类型,来进行阻拦检测。

二、根本环境建立

不管咱们封装sdk,仍是开发什么功用,在给别人运用的时候,一定是本着简略快捷的主旨,要不然,辛辛苦苦操作了一番,比原有的还杂乱,岂不是,既违反了主旨,也很难普及运用,所以,Git的Hook,也要依据这个思想。

为了完成这样的一个简略快捷的标准查看,确实研究了一番,经过各项比较及实践的操作,终究仍是运用Node.js来完成这样的一个功用,原因无非便是简略,这个在第一篇中现已给出了答案。

1、装置 Node.js

假如现已装置,可直接第2步

Node.js中答应运用 JavaScript 开发服务端以及指令行程序,咱们能够去官网 nodejs.org 下载最新版别的装置程序,然后一步一步进行装置就能够了。

2、履行init指令

新建目录,在当时目录下履行如下指令,创立package.json文件

npm init -y

指令履行后,如下图所示:

Android打造专有hook第二篇,走进规范第一步

里边的内容没什么好说的,包括根本的,作者,介绍,履行脚本信息等,这个之前的文章里讲述过,就不过多赘述了。

3、装置pre-commit

意图在提交信息前进行阻拦查看。

 npm install pre-commit --save-dev

装置成功后,当时目录下多出一个文件夹node_modules,此文件下用来寄存下载装置的包文件夹,里边有咱们要运用到的功用,其实和Android中lib目录很类似,都是一些供给功用的库。

Android打造专有hook第二篇,走进规范第一步

4、创立履行程序文件

在当时目录下,新建一个js文件,姓名自己界说,我这儿创立了一个gitExec.js文件,如下图:

Android打造专有hook第二篇,走进规范第一步

5、更改package.json文件

打开package.json文件,可依照下面的办法进行更改,最重要的是scripts脚本履行这儿,lint指向你刚才创立的js文件。

{
  "name": "android_git_hook",
  "version": "1.0.0",
  "description": "Android端git标准查看",
  "scripts": {
    "lint": "node gitExec.js"
  },
  "author": "AbnerMing",
  "license": "ISC",
  "pre-commit": [
    "lint"
  ],
  "devDependencies": {
    "pre-commit": "^1.2.2"
  },
  "dependencies": {
    "pre-commit": "^1.2.2"
  }
}

经过上面的五步,咱们的环境建立就完成了,后续咱们的逻辑处理,均在你创立的js文件里,这个需求重点强调一下。

三、创立动态装备文件

环境建立之后,在写标准查看逻辑之前,需求创立可装备的动态文件,这个文件是十分重要的,是需求露出给开发者的,也便是说,开发人员是依据这个装备文件,来进行操作标准查看的,详细需求包括什么字段,需求咱们依据实践的业务,或许自己的拓展进行设置的,我自己创立的动态文件如下:

Android打造专有hook第二篇,走进规范第一步

内容如下:

#git提交装备文件
#git提交前是否进行检测,true:检测,false:不检测
gitCommitSwitch=true
#是否进行增量更新(增量仅指令可用),true为增量,false为查看整个文件
gitIncrement=false
#git检测类型,0:悉数,1:string文件Name,2:图片命名,3:layout,4:类命名,
#5:类注释,6:办法注释,7:办法命名,8:变量命名,9:try catch
gitCheckType=0
#git提交办法,true为东西,false为指令办法
gitCommand=true

咱们能够看到我自己界说的文件格局为.android,这个咱们能够自界说,.aa,.bb都行,什么格局都能够,是一个文件就行,究竟,咱只关怀里边的内容,所谓的格局没有区别。

至于里边的内容,看咱们自己实践的需求,自己去编写,你想经过什么字段来控制,或许想要完成一个什么样的标准查看,都能够在这儿动态装备,露出给开发人员,当然,咱们能够直接运用我的,或许在我的根底之上进行拓展都行。

四、代码初始化

万事具备,就差代码逻辑编写了,这儿需求温馨提示一下,虽然是Android端的Hook标准查看,但一切的代码逻辑都是经过Js来完成的,不明白Js的老铁,建议看一下,关于咱们有编程根底的人来说,很简略的。有的老铁问了,我不明白Js,能否搞出来呢?我的答复是,问题不大,我尽量把代码注释标注得很清楚,让咱们一看便理解。

1、创立履行程序

当咱们履行Git提交时,经过pre-commit映射到了咱们自界说的js文件中,在这个js文件中,咱们就需求进行相关逻辑编写,首要,界说了一个startTask函数,并且当即履行了startTask函数,也便是Git提交时会触发界说的这个startTask函数。

startTask函数里又调用了一个lint函数,接下来的一切的逻辑判别都是经过此函数,咱们能够看到,调用了process的exit办法,之所以要调用,意味着,逻辑是由咱们自己来处理,也便是在lint办法里,是履行仍是退出,需求依据判别来收效。

/**
 * Author:AbnerMing
 * Time:2022-9-13
 * Desc:git履行commit前判别
 * */
//标准查看函数,一切的逻辑判别都是经过此函数
let lint = function (cb) {
};
//调用 lint 函数
let startTask = function () {
  lint(function () {
    //它能够是0或1,0表明没有任何类型的毛病完毕进程,而1表明因为某种毛病而完毕进程
    process.exit(1);
  })
}
// 调用startTask办法,进行履行查看
startTask();

2、读取装备文件

引入fs,文件操作模块,因为咱们要读取装备文件,这个fs模块是必不可少的。

let fs = require('fs');

声明成员变量,便于接下来的程序判别

/*
*git检测类型,0:悉数,1:string文件Name,2:图片命名,3:layout,4:类命名,
*5:类注释,6:办法注释,7:办法命名,8:变量命名,9:try catch
* */
var mCommitType;
//git检测开关,true:开,false:关
var mCommitOpen;
//是否进行增量更新(增量仅指令可用),true为增量,false为查看整个文件
var mCommitIncrement;
//git提交办法,true为东西,false为指令办法
var mGitCommand;

读取装备文件,取出参数值并赋值给成员变量

//标准查看函数,一切的逻辑判别都是经过此函数
let lint = function (cb) {
    //读取文件信息
    let path = require('path');
    let dirname = path.join(__dirname);
    try {
        //读取装备文件,查找对应的装备信息
        let data = fs.readFileSync(dirname + "/gitCommitConfig.android", 'utf-8');
        data.split(/\r?\n/).forEach((line, position) => {
            if (position === 2) {
                let open = line.split("=")[1];
                mCommitOpen = open.toString();//git检测开关
            }
            if (position === 4) {
                let increment = line.split("=")[1];
                mCommitIncrement = increment.toString();//是否进行增量更新
            }
            if (position === 7) {
                let type = line.split("=")[1];
                mCommitType = type.toString();//git检测类型
            }
            if (position === 9) {
                let type = line.split("=")[1];
                mGitCommand = type.toString();//git提交办法
            }
        });
        //依据装备文件进行逻辑判别
    } catch (e) {
        if (e.message.indexOf("gitCommitConfig.android") !== -1) {
            //没有文件,向运用者展示过错信息
            console.log("\n");
            log("\n短少装备文件[gitCommitConfig.android],请核对后再提交\n", 0);
            log("请在项目根目录下创立[gitCommitConfig.android]文件\n", 0);
            log("内容如下\n", 0);
            log("#git提交装备文件\n" +
                "#git提交前是否进行检测,true:检测,false:不检测\n" +
                "gitCommitSwitch=true\n" +
                "#是否进行增量更新(增量仅指令可用),true为增量,false为查看整个文件\n" +
                "gitIncrement=false\n" +
                "#git检测类型,0:悉数,1:string文件Name,2:图片命名,3:layout,4:类命名,\n" +
                "#5:类注释,6:办法注释,7:办法命名,8:变量命名,9:try catch\n" +
                "gitCheckType=0\n" +
                "#git提交办法,true为东西,false为指令办法\n" +
                "gitCommand=true\n", 3);
        }
        cb(1);//毛病而完毕进程
    }
};

咱们能够看到,我在读取装备文件的时候,进行了一个异常判别,判别的意图在于,可能运用者因为粗心,没有履行相关指令生成装备文件,或许装备删除了,那么咱们就要捕获异常,给运用者抛出提示,让运用者依照要求再生成一份。

log呢,是一个函数,里边封装了一层,意图便是为了区别东西提交仍是指令行办法提交,假如指令行办法提交,就能够进行彩色区别。

//log日志展示,其实便是提交信息展示,指令提交进行特别符合处理
function log(message, type) {
    //东西提交
    if (mGitCommand === "true") {
        console.log(message);
    } else {
        //指令行办法
        if (type === 2) {
            console.log("\x1B[32m%s\x1B[39m", message);//色彩:green
        } else if (type === 1) {
            console.log('\x1B[36m%s\x1B[39m', message);//色彩:cyan
        } else if (type === 0) {
            console.log('\x1B[31m%s\x1B[39m', message);//色彩:red
        } else if (type === 3) {
            console.log('\x1B[33m%s\x1B[39m', message);//色彩:yellow
        }
    }
}

更多色彩值如下

    'bold'          : ['\x1B[1m%s\x1B[22m'],
    'italic'        : ['\x1B[3m%s\x1B[23m'],
    'underline'     : ['\x1B[4m%s\x1B[24m'],
    'inverse'       : ['\x1B[7m%s\x1B[27m'],
    'strikethrough' : ['\x1B[9m%s\x1B[29m'],
    'white'         : ['\x1B[37m%s\x1B[39m'],
    'grey'          : ['\x1B[90m%s\x1B[39m'],
    'black'         : ['\x1B[30m%s\x1B[39m'],
    'blue'          : ['\x1B[34m%s\x1B[39m'],
    'cyan'          : ['\x1B[36m%s\x1B[39m'],
    'green'         : ['\x1B[32m%s\x1B[39m'],
    'magenta'       : ['\x1B[35m%s\x1B[39m'],
    'red'           : ['\x1B[31m%s\x1B[39m'],
    'yellow'        : ['\x1B[33m%s\x1B[39m'],
    'whiteBG'       : ['\x1B[47m%s\x1B[49m'],
    'greyBG'        : ['\x1B[100m%s\x1B[49m'],
    'blackBG'       : ['\x1B[40m%s\x1B[49m'],
    'blueBG'        : ['\x1B[44m%s\x1B[49m'],
    'cyanBG'        : ['\x1B[46m%s\x1B[49m'],
    'greenBG'       : ['\x1B[42m%s\x1B[49m'],
    'magentaBG'     : ['\x1B[45m%s\x1B[49m'],
    'redBG'         : ['\x1B[41m%s\x1B[49m'],
    'yellowBG'      : ['\x1B[43m%s\x1B[49m']

代码初始化完成之后,后面的便是依据动态装备文件的参数,来实践的操作标准查看了,行,老铁们,这篇先到这儿,下篇咱们继续。