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

标签 git bash githooks

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

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

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

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 文件。符合以下任一条件:

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

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

最佳答案

另一种方法是 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 整个文件,而不是专注于添加的行(这就是 grep -E "^\+[^\+]" 的用途,用于 grep 以 ++ 开头的那些行)

这意味着,如果旧提交中的某个键不正确,您仍然会检测到它,即使您所做的唯一更改是修改评论等。


经过测试和修复后,OP rubo77 settled 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
...

关于git hook 来测试文件是否包含正确的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34191223/

相关文章:

git - IntelliJ (Git) - 清除存储并恢复它

bash - POSIX 和 Bash 脚本

git post-receive hook 抓取提交消息并回发到 URL

eclipse - 如何使用 Eclipse 压缩提交?

Gitlab在推送git用户时提示输入密码

git - 推送到远程文件系统时是否可以配置 Git 以设置全局写入权限?

bash - 如何在bash中删除现有数组中的重复元素?

bash - 命名路径的 kubectl jsonpath 表达式

git - 在 git init 上执行脚本

git - 防止推送到某些文件中包含选项卡的 git(例如 *.cpp、*.h、CMakeLists.txt)