利用git hooks,在服务器端每次接收到push的时候进行文件信息检查,若超过限制则拒绝提交。
具体实现:在update hook中对提交的文件进行检查,利用git log
命令查询所有新提交的分支,利用git cat-file
命令递归查询文件树、查询文件大小,若超限则返回1拒绝提交。
#!/bin/bash
#
# An example hook script to block unannotated tags from entering.
# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
#
# To enable this hook, rename this file to "update".
#
# Config
# ------
# hooks.allowunannotated
# This boolean sets whether unannotated tags will be allowed into the
# repository. By default they won't be.
# hooks.allowdeletetag
# This boolean sets whether deleting tags will be allowed in the
# repository. By default they won't be.
# hooks.allowmodifytag
# This boolean sets whether a tag may be modified after creation. By default
# it won't be.
# hooks.allowdeletebranch
# This boolean sets whether deleting branches will be allowed in the
# repository. By default they won't be.
# hooks.denycreatebranch
# This boolean sets whether remotely creating branches will be denied
# in the repository. By default this is allowed.
#
# --- Command line
refname="$1"
oldrev="$2"
newrev="$3"
# --- Safety check
if [ -z "$GIT_DIR" ]; then
echo "Don't run this script from the command line." >&2
echo " (if you want, you could supply GIT_DIR then run" >&2
echo " $0 <ref> <oldrev> <newrev>)" >&2
exit 1
fi
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
echo "usage: $0 <ref> <oldrev> <newrev>" >&2
exit 1
fi
# check commit file size (MB)
export maxFileSize=20
export warningFileSize=10
# check repo size (GB)
export maxRepoSize=3
export warningRepoSize=1
# echo "tree sha"
# tree_sha=`git cat-file -p $newrev | grep tree | awk '{print $2}'`
# echo $tree_sha
IFS=$'\n\n'
# echo "tree info "
# git cat-file -p $tree_sha
export totalRepoSize=0
check_file_size(){
# echo "$1"
for line in `git cat-file -p $1`;
do
# echo "line: $line"
file_type=`echo $line | awk '{print $2}'`
file_sha=`echo $line | awk '{print $3}'`
# echo "file_type: $file_type"
# echo "file_sha: $file_sha"
if [[ $file_type == "tree" ]];then
check_file_size $file_sha $2
else
# echo `git cat-file -s $file_sha`
# echo $(($maxFileSize * 1024 * 1024))
file_size=`git cat-file -s $file_sha`
totalRepoSize=$(($totalRepoSize + $file_size))
if [ $file_size -ge $(($maxFileSize * 1024 * 1024)) ];then
file_name=`echo $line | awk '{print $4}'`
echo -e "\e[1;31mERROR:\033[0m File '$file_name' size $(($file_size / 1024 / 1024)) MB >= $maxFileSize MB! Try reduce file size."
echo -e "\e[1;36mFile SHA:\033[0m\t $file_sha"
echo -e "\e[1;36mCommit SHA:\033[0m\t $2"
exit 1
fi
if [ $file_size -ge $(($warningFileSize * 1024 * 1024)) ];then
file_name=`echo $line | awk '{print $4}'`
echo -e "\e[1;33mWARNING:\033[0m File '$file_name' size $(($file_size / 1024 / 1024)) MB >= $warningFileSize MB! Don't commit too many large files!"
echo -e "\e[1;36mFile SHA:\033[0m\t $file_sha"
echo -e "\e[1;36mCommit SHA:\033[0m\t $2"
fi
fi
done
}
# check_file_size $tree_sha
if [[ $newrev == "0000000000000000000000000000000000000000" ]];then # delete a branch
exit 0
fi
export commits=`git log HEAD..$newrev | grep "commit" | awk '{print $2}'`
# echo $commits
for commit in $commits
do
tree_sha=`git cat-file -p $commit | grep tree | awk '{print $2}'`
# echo $commit
# echo $tree_sha
check_file_size $tree_sha $commit
done
# echo "totalRepoSize: $totalRepoSize"
if [ $(($totalRepoSize / 1024)) -ge $(($maxRepoSize * 1024 * 1024)) ];then
echo -e "\e[1;31mERROR:\033[0m Repository size > $maxRepoSize GB! Try reduce repo size!"
exit 1
fi
# echo "totalRepoSize: $totalRepoSize"
if [ $(($totalRepoSize / 1024)) -ge $(($warningRepoSize * 1024 * 1024)) ];then
echo -e "\e[1;33mWARNING:\033[0m Repository size > $warningRepoSize GB!"
exit 1
fi
# --- Finished
exit 0