git钩子语法检查

git钩子语法检查,git,Git,尝试为git存储库创建php语法检查挂钩。当我发现一个代码片段可以做到这一点时,我很高兴 但代码片段脚本似乎有一个缺陷。它执行 git diff-index --cached --name-only HEAD 获取索引中的文件列表。现在它为列表中的每个文件运行php-l。该漏洞是工作副本和临时区域之间的文件可能不同。如果暂存区php有语法错误,但工作副本版本没有,则不会发现语法错误,并且提交成功,这是要防止的 这是一个需要解决的重要问题,还是有什么方法可以在每个文件的暂存版本上运行php-l?

尝试为git存储库创建php语法检查挂钩。当我发现一个代码片段可以做到这一点时,我很高兴

但代码片段脚本似乎有一个缺陷。它执行

git diff-index --cached --name-only HEAD
获取索引中的文件列表。现在它为列表中的每个文件运行php-l。该漏洞是工作副本和临时区域之间的文件可能不同。如果暂存区php有语法错误,但工作副本版本没有,则不会发现语法错误,并且提交成功,这是要防止的


这是一个需要解决的重要问题,还是有什么方法可以在每个文件的暂存版本上运行php-l?

我不确定这里是否有问题

您提到的片段可能来自博客帖子。
它包括:

接下来,我们使用一些参数调用
git diff index

首先,我们添加了
--cached
,告诉Git我们只需要提交的文件
然后,我们添加
--name only
,告诉Git只输出正在提交的文件的名称

似乎即将提交的文件正是预提交钩子想要检查的文件。
即使它们与工作目录中的文件不同,也要提交它们的版本(在索引中)。它是同一个版本,将被发送到
php-l
进程


实际上,问题不在于
git diff索引本身(带或不带
--完整索引
),而在于您读取索引中文件内容的方式

  • 只需尝试从文件名访问文件(有访问工作副本的风险)
exec(“php-l”.escapeshellarg($file),$lint_output,$return);
  • (中提到的)将向Git询问实际内容:
结果=$(git cat文件-p$sha |/usr/bin/env$PHP|u bin-l2>/dev/null) 使用是这里的关键,访问Git repo中的对象(即不在“工作目录”中)

我很高兴使用它。希望它也能满足你的需要


它使用
git diff index--cached--full index

原因预提交钩子不适合在团队中工作您应该使用安装在服务器端的预接收钩子拒绝所有php语法无效和编码标准不正确的提交

我已经为该pupose创建了预接收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)
#用于检查PHP语法和验证编码标准的服务器端git钩子脚本
#取决于:PHP_代码嗅探器(http://pear.php.net/package/PHP_CodeSniffer/)
#安装:将此脚本复制到/hooks/pre-receive
#!/usr/bin/python
导入操作系统
导入系统
oldrev,newrev,ref=sys.stdin.read().strip().split(“”)
test_file=os.popen('mktemp').read().strip()
编码标准='PSR2'
对于os.popen中的行('git diff--name only%s%s'(oldrev,newrev))。readlines():
extension=line.split('.')[-1].strip()
文件名=line.strip()
如果(扩展名='php'):
系统(“git cat文件-p%s:%s>%s”%(新版本,文件名,测试文件))
如果0!=system('php-l'+test_file+'>/dev/null'):
打印“文件%s中的PHP语法错误”%(文件名)
系统出口(1)
如果0!=操作系统(“phpcs-n——标准=%s%s”%(编码标准,测试文件)):
打印“文件%s中的编码标准失败”%(文件名)
系统出口(2)

是的,这就是我要说的代码。在$output中,您将获得要提交的文件列表,正确。但我认为你的最后一句话错了。发送到php-l的是工作副本版本,而不是临时区域版本。这是一个错误。由takeshin链接的钩子似乎做得更好。@zedoo:我已经更新了我的答案,以反映这里的实际问题(不是
git diff index
)是的,这比文章中的钩子做得好得多。钩子很好,但是需要稍微修改,以便我可以使用它。我无法获取正确的文件名和扩展名,因为“cut”commandLink现在已失效:(链接已断开:-( result=$(git cat-file -p $sha | /usr/bin/env $PHP_BIN -l 2>/dev/null)
# 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)