我们的目标是在开发者 git commit
之前自动进行代码风格检查,如果检查有任何错误,则提交失败。所以这个检查需要是在本地进行的。让错误尽早地消灭在源头。
幸好,git 提供了 pre-commit hooks 可以满足我们的要求。
git pre-commit 默认是关闭的,打开的方式如下:把本地代码工程中 .git/hooks/ 目录下的 pre-commit.sample
文件重命名为 pre-commit
即可。然后稍作修改如下:
#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
# Redirect output to stderr.
exec 1>&2
cpplint=cpplint.py
sum=0
filters='-whitespace/line_length,-build/include'
# for cpp
for file in $(git diff-index --name-status $against -- | grep -E '\.[ch](pp)?$' | awk '{print $2}'); do
$cpplint --filter=$filters $file
sum=$(expr ${sum} + $?)
done
if [ ${sum} -eq 0 ]; then
exit 0
else
exit 1
fi
然后将cpplint 目录加入到环境变量 PATH中,以便在任何目录都能调起cpplint.py
。(注意:如果想运行cpplint.py
,本地环境中还得安装python3。)
我们来尝试用小乌龟提交一个有错误的代码:
点击git commit
按钮:
main.cpp:0: No copyright message found. You should have a line: "Copyright [year] <Copyright Owner>" [legal/copyright] [5]
main.cpp:2: Line contains invalid UTF-8 (or Unicode replacement character). [readability/utf8] [5]
main.cpp:7: Could not find a newline character at the end of the file. [whitespace/ending_newline] [5]
Done processing main.cpp
Total errors found: 3
pre-commit
脚本的返回值为非 0 值,则认为有错误,就会提交失败。
上面这个例子把 filters
参数直接写在这个脚本里面了,实际应用时最好写到 CPPLINT.cfg
配置文件里面。
发现提交的代码中有不符合代码规范的地方,提交失败;本地修改完所有错误项后,在次提交,OK。
注意:这种自动提交检测时是对提交的所有改动文件进行全量检测,还做不到只检测文件中的片段代码改动点。不过相对于对一整目录的盲目扫描检测,这已经是向前走了一大步了。