在预接收挂钩中检查该文件是否为二进制文件

时间:2017-06-07 10:43:21

标签: git perl shell

在服务器端的git pre-rec钩子中,我使用此命令获取提交中的文件列表:

my @new_file_list =  `git diff --name-only $old..$new`;;

通过循环获取每个文件的大小:

foreach $file (@new_file_list)
{
  $size = `git cat-file -s $new:$file`;

通过使用what命令,我可以得到一个布尔变量,如果提交中的文件是二进制的,那将定义? 所以我在输入中有文件名,而 $ old $ new 修订版,如果文件是二进制文件,那么命令可以定义什么?

提前致谢。

3 个答案:

答案 0 :(得分:4)

Perl有许多文件测试操作符,它们会告诉你关于文件的各种事情(你已经在使用-s)。其中包括以下内容(取自the documentatio n):

  

-T File是ASCII或UTF-8文本文件(启发式猜测)。

     

-B File是一个“二进制”文件(与-T相反)。

值得强调的是,这只是一种启发式方法。 Perl检查文件的开头并检查字符的哪些部分看起来是可打印的。

所以你可以在你的代码中使用这些:

if (-B $filename) {
  # file is (probably) binary
}

答案 1 :(得分:4)

这取决于你想要实现的目标和成本。如果你想防止意外提交由于编译而导致的文件,只需添加一个.gitignore文件,使其不被提交(顺便说一句,这总是一个好主意,也可以排除备份副本和编辑器临时文件)并在钩子检查中如果已提交文件的扩展名在允许列表中。

上面提到的Perl中的-T / -B检查很不错,但是,阅读提议的文档很好。它的效率低于检查扩展名,但它使用文件的真实内容给出答案。

如果-B / -T启发式(如文档中所述)不适合您的需求,请使用文件。在Perl中,您几乎没有可用的包:

File::Type
File::LibMagic
File::MMagic

您将收到该文件的MIME类型,您需要编写一些逻辑来解释结果。

除非没有我们不知道的具体要求,否则我个人会坚持使用.gitignore并检查扩展名。可选地,对于将禁止文件存入存储库的开发人员,您可以考虑某种类型的棒(最好是虚拟的,因为体罚通常是不受欢迎的)。

答案 2 :(得分:1)

您可能已经注意到Git有时会告诉您“二进制文件......并且......不同”。

根据this answer来说 一个类似的问题Git通过查看文件来检查文件是否是二进制文件 前8,000个字节。如果它们包含NUL字节,那么Git会将文件视为 是二元的。

您可以在钩子中使用git diff并让Git决定:

if git diff --numstat $old $new -- $file | grep -q -P -e '-\t-\t'; then
    # binary
else
    # text
fi

对于与Git无关且不在任何存储库中的文件,这甚至是可能的。如果

git diff --no-index --numstat /dev/null $some_file

打印dash-TAB-dash-TAB然后文件是二进制的(从Git的角度来看)。来自 docs

git diff --no-index [--options] [--] [<path>…​]
     

此表单用于比较文件系统上给定的两个路径。

     

...

--numstat
     

与--stat类似,但以十进制显示添加和删除的行数      符号和路径名没有缩写,使其更加机器友好。      对于二进制文件,输出两个 - 而不是说0 0。