我正在编写一个预提交的钩子。我想php -l
对所有带有.php扩展名的文件运行。但是我被困住了。
我需要获取暂存的新文件/更改文件的列表。删除的文件应排除在外。
我尝试使用git diff
和git ls-files
,但是我认为我需要帮助。
Answers:
git diff --cached --name-status
将显示上演的摘要,因此您可以轻松排除已删除的文件,例如:
M wt-status.c
D wt-status.h
这表明在暂存区域(索引)中wt-status.c被修改,wt-status.h被删除。因此,仅检查未删除的文件:
steve@arise:~/src/git <master>$ git diff --cached --name-status | awk '$1 != "D" { print $2 }'
wt-status.c
wt-status.h
您将不得不跳过多余的圈来处理带有空格的文件名(git diff的-z选项和一些更有趣的解析)
获得相同列表的更简洁的方法是:
git diff --cached --name-only --diff-filter=ACM
这将返回需要检查的文件列表。
但是,仅php -l
在工作副本上运行可能不是正确的选择。如果您正在执行部分提交,即仅选择当前工作集和HEAD的差异的子集作为提交,则测试将在您的工作集上运行,但将证明您的从未存在过的提交磁盘。
要正确执行此操作,应将整个暂存的图像提取到临时区域,然后在此处进行测试。
rm -rf $TEMPDIR
mkdir -p $TEMPDIR
git checkout-index --prefix=$TEMPDIR/ -af
git diff --cached --name-only --diff-filter=ACM | xargs -n 1 -I '{}' \bin\echo TEMPDIR/'{}' | grep \\.php | xargs -n 1 php -l
有关其他实现,请参见为Git构建更好的预提交挂钩。
php -l
。这就是我们最终得到的结果。在这里看到:github.com/phpbb/phpbb3/blob/develop-olympus/git-tools/hooks/...
git show :FILENAME | php -l
。
这是我用于Perl检查的内容:
#!/bin/bash
while read st file; do
# skip deleted files
if [ "$st" == 'D' ]; then continue; fi
# do a check only on the perl files
if [[ "$file" =~ "(.pm|.pl)$" ]] && ! perl -c "$file"; then
echo "Perl syntax check failed for file: $file"
exit 1
fi
done < <(git diff --cached --name-status)
对于PHP,它将如下所示:
#!/bin/bash
while read st file; do
# skip deleted files
if [ "$st" == 'D' ]; then continue; fi
# do a check only on the php files
if [[ "$file" =~ ".php$" ]] && ! php -l "$file"; then
echo "PHP syntax check failed for file: $file"
exit 1
fi
done < <(git diff --cached --name-status)
如果使用-a标志指定了提交调用,则git diff --cached是不够的,并且无法确定该标志是否已被挂起。如果提交的参数对于钩子可用,将很有帮助。
git status --porcelain | grep -E -v '^[? ]'
git status --porcelain | perl -ane 'print $F[1],qq(\n) if m/^[ACM] /'
是一个更好的答案。它具有使用--porcelain选项的优势,可以保证永远不变。如果perl对您来说太重了,请使用自己的解析器。