尝试为git存储库创建一个php语法检查钩子。当我发现一个完全符合这一要求的代码片段时,我很高兴。
但似乎代码段脚本有一个缺陷。它执行
git diff-index --cached --name-only HEAD
获取索引中的文件列表。现在它为该列表上的每个文件运行php -l。缺陷是工作副本和临时区域之间的文件可能不同。如果暂存区域php有语法错误,但工作副本版本没有,则没有找到语法错误,并且提交成功,这是要防止的事情。
这是一个难以解决的问题,还是有办法在每个文件的登台版本上运行php -l?
答案 0 :(得分:7)
我很高兴使用这个php syntax validation hook。希望它也能满足您的需求。
它使用git diff-index --cached --full-index
。
答案 1 :(得分:3)
我不确定这里是否有问题。
您提到的代码段可能来自博文Don’t Commit That Error 它包括:
接下来,我们使用一些参数调用
git diff-index
首先,我们添加--cached
告诉Git我们只想要提交的文件。
然后,我们添加--name-only
告诉Git只输出正在提交的文件的名称。
似乎即将提交的文件正是预提交钩子想要检查的文件
即使它们与工作目录中的文件不同,也是要提交的版本(在索引中)。它是将发送到php -l
进程的相同版本。
实际上,问题不在于git diff-index
本身(有或没有--full-index
),就像您在索引中读取文件内容一样
exec("php -l " . escapeshellarg($file), $lint_output, $return);
result=$(git cat-file -p $sha | /usr/bin/env $PHP_BIN -l 2>/dev/null)
使用 git cat-file
是关键,访问Git仓库中的对象(即不在“工作目录”中)
答案 2 :(得分:0)
原因预提交挂钩不适合在团队中工作,您应该使用服务器端安装的预接收挂钩拒绝所有提交无效的PHP语法和编码标准不正确。
我为该广告创建了预接收 python脚本:
# A server-side git hook script for checking PHP syntax and validating coding standard
# Depends on: PHP_CodeSniffer (http://pear.php.net/package/PHP_CodeSniffer/)
# Install: copy this script to <server side repo location>/hooks/pre-receive
#!/usr/bin/python
import os
import sys
oldrev, newrev, ref = sys.stdin.read().strip().split(' ')
test_file = os.popen('mktemp').read().strip()
coding_standards = 'PSR2'
for line in os.popen('git diff --name-only %s %s' % (oldrev, newrev)).readlines():
extension = line.split('.')[-1].strip()
file_name = line.strip()
if(extension == 'php'):
os.system("git cat-file -p %s:%s > %s" % (newrev, file_name, test_file))
if 0 != os.system('php -l ' + test_file + ' > /dev/null'):
print "PHP Syntax error in file %s" % (file_name)
sys.exit(1)
if 0 != os.system("phpcs -n --standard=%s %s" % (coding_standards, test_file)):
print "Coding standards fail in file %s" % (file_name)
sys.exit(2)