检查为 git 提交暂存的任何文件是否与白名单不匹配



由于自动提交和推送的脚本存在一些问题,我想实现一个白名单。

计划是,只允许在路径中使用模式"foo"和"bar"提交。

#!/bin/sh
WHITELIST="foo bar"
WRKDIR=/home/athur/workwork/test/repo

cd $WRKDIR
git add -A
for file in `git diff --cached -p --name-status | cut -c3-`; do
if [[ "$file" == *"$WHITELIST"* ]] ; then
echo "$file is on whitelist"
else
echo "$file is not on whitelist. Commit aborted."
exit 1
fi
done

问题是,它总是使用"else"子句。 我找不到问题。谢谢

作为最佳实践方法,请考虑:

#!/usr/bin/env bash
#              ^^^^ important: [[ ]] is not guaranteed to work with bin/sh
whitelist_re='(foo|bar)'
workdir=/home/athur/workwork/test/repo
cd -- "$workdir" || exit
git add -A
while IFS= read -r filename; do
if [[ $file =~ $whitelist ]]; then
echo "$file is on whitelist" >&2
else
echo "$file is not on whitelist; commit aborted." >&2
exit 1
fi
done < <(git diff --cached --name-only)

要演练更改,请执行以下操作:

  • Shebang 将bash指定为 shell,这保证了像[[ ]]<(...)这样的扩展将可用——这是/bin/sh无法保证的。
  • 使用while read循环而不是尝试使用for遍历面向行的数据;请参阅DontReadLinesWithFor来解释此更改背后的原因。
  • 白名单被指定为符合 ERE 的正则表达式,以便=~可用于测试值是否匹配。
  • 我们首先使用--name-only仅生成名称,而不是使用git diff --cached --name-status然后使用cut在事后删除状态数据。
  • 使用小写变量名称符合 http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html 中给出的约定,指定 POSIX 定义的工具将全大写的 shell 和环境变量名称用于其自身目的,并且至少保留一个小写字符的名称供应用程序使用。(请记住,设置 shell 变量会覆盖任何同名的环境变量,因此即使不使用export,这些约定也适用(。

顺便说一句,如果您只是想找出是否存在任何不匹配的文件,而不知道这些文件是哪些文件,您可以使用:

#!/bin/sh
#      ^^ actually safe here, as no non-POSIX functionality is used
whitelist_re='foo|bar'
if git diff --cached --name-only | grep -qEv "$whitelist_re"; then
echo "At least one file is not on whitelist; commit aborted" >&2
exit 1
fi

使用显式列表

在这种情况下,==不是对称的,**似乎用得不好。

试试"$WHITELIST" == *"$file"*.

(灵感来自如何检查 BASH 中的列表中是否存在变量(

请注意,使用您的WHITELIST,只有foobar的文件才会被列入白名单。

检测模式

如果需要检测单个模式,则可能需要构造如下函数:

for entry in $WHITELIST ; do 
if [[ "$file" =~ $entry ]] ; then
return 0
fi
done
return 1

相关内容

最新更新