git 用于测试文件是否包含正确数据的挂钩

git hook to test if a file contains the right data

我有一个 git 存储库,其中的关键文件必须全部采用

格式
#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

我想停止提交 changed/new 格式不正确的密钥文件。以下任何一项:

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

另一种方法是 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 to freifunk-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
...