git hook来测试文件是否包含正确的数据

时间:2015-12-09 23:48:13

标签: git bash githooks

我有一个git repo,其密钥文件必须全部采用格式

#possible comment
key "<key with 64 chars>"; # possible comment
vpn .... #optional line

我想在我们的git存储库中添加一个钩子,当你尝试提交一个新文件时,事先在存储库中的所有文件上检查这个正则表达式:

cat *|grep -v -E "^\s*key\s+\"[0-9a-f]{64}\";\s*(#.*)*$"|grep -v -E "(^#|vpn|^$)"

我创建了一个.git/hooks/pre-commit文件:

#!/bin/sh

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

diffstr=$(git diff --cached $against | sed 's/^+//g' | grep -E "^\+[^\+]" \
| grep -v -E "^key \"\w{64}\";\s*(#.*)*$" | grep -v -E "(^#|vpn|^$)")
if [ "$diffstr" != "" ] ; then
    echo "You have a malformed key in your changes, you can't commit until it has been corrected:"
    echo $diffstr
    exit 1
fi

我希望停止提交格式正确的更改/新密钥文件。以下任何一项:

  • 不要以key
  • 开头
  • 不要使用" - 引号
  • 不要以;结尾(可选地后跟评论)
  • 其中密钥不是64个十六进制字符。
  • 任何其他不以评论#
  • 开头的行

但我的解决方案仍然无法阻止我提交错误的密钥文件。我做错了什么?

1 个答案:

答案 0 :(得分:1)

另一种方法是grep文件,而不是直接传播内容 要检查的文件列表是:

  git diff --cached --name-only --diff-filter=ACM $against --

所以

#!/bin/bash
exec 1>&2
git diff --cached --name-status --diff-filter=ACM | cut -d$'\t' -f2 \
| while read st file; do
  diffstr=$(cat "$st" | grep -v -E "^key \"\w{64}\";\s*(#.*)*$" \
  | grep -v -E "(^#|vpn|^$)")
  if [ "$diffstr" != "" ] ; then
    echo "$st: you have a malformed key in your changes, you can't commit until it has been corrected:"
    echo $diffstr
    exit 1
  fi
done

缺点是它会压缩整个文件,而不是专注于添加的行(这是grep -E "^\+[^\+]"的用途,用于填充以++开头的那些行

这意味着如果某个密钥在旧提交中不正确,您仍然会检测到它,即使您所做的唯一更改,例如,修改注释。

经过测试和修正,OP rubo77 settledfreifunk-kiel/fastd-git-hook/git/hooks/pre-commit

#!/bin/bash
#
# A 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.
#
# This script checks if all files to be committed fit the needs for 
# a valid fastd-keyfile so it can be pulled to all Freifu9nk gateways
# and used as public key

# Redirect output to stderr.
exec 1>&2

while read keyfile file; do
  # sanitize last linebreak:
  tail -c1 "$keyfile" | read -r _ || echo >> "$keyfile" 
  diffstr=$(cat "$keyfile" | grep -v -E "^\s*key\s+\"\w{64}\";\s*(#.*)*$" \
  | grep -v -E "(^\s*#|^\s*remote|^$)")
  if [ "$diffstr" != "" ] ; then
    echo "$keyfile: you have a malformed key in your changes , you can't commit until it has been corrected:"
    echo "$diffstr"
    exit 1
  fi
done < <(git diff --cached --name-status --diff-filter=ACM | cut -f2)

# checks
...