95 lines
2.9 KiB
Bash
Executable File
95 lines
2.9 KiB
Bash
Executable File
#!/bin/bash -eu
|
|
#
|
|
# Reject commits with binary files, which should have used LFS instead. Allow
|
|
# overriding when "override restrictions" is in the commit message.
|
|
#
|
|
# To enable this hook, rename this file to "pre-receive" or place it in
|
|
# a "pre-receive.d" folder.
|
|
|
|
# Use 'strict mode': http://redsymbol.net/articles/unofficial-bash-strict-mode/
|
|
set -o pipefail
|
|
|
|
nullsha="0000000000000000000000000000000000000000"
|
|
status=0
|
|
# This is the message to include in your commit to override.
|
|
commit_override_msg="override restrictions"
|
|
|
|
handle_pipefails() {
|
|
# ignore exit code 141 from simple command pipes
|
|
# - use with: cmd1 | cmd2 || handle_pipefails $?
|
|
(( $1 == 141 )) && return 0
|
|
return $1
|
|
}
|
|
|
|
# Read stdin for ref information.
|
|
while read oldrev newrev refname; do
|
|
# Skip branch deletions.
|
|
if [ "$newrev" = "$nullsha" ]; then
|
|
continue
|
|
fi
|
|
|
|
# Set oldrev to HEAD if this is branch creation.
|
|
if [ "$oldrev" = "$nullsha" ]; then
|
|
oldrev="HEAD"
|
|
fi
|
|
|
|
# Check for branches and tags, but not pull requests in refs/pull. Otherwise Gitea
|
|
# fails to create a pull request without explaining why.
|
|
if [[ "$refname" == refs/heads/* ]]; then
|
|
:
|
|
elif [[ "$refname" == refs/tags/* ]]; then
|
|
:
|
|
else
|
|
exit 0
|
|
fi
|
|
|
|
# Loop over each commit.
|
|
for commit in $(git rev-list --objects ${oldrev}..${newrev} |
|
|
git cat-file --batch-check='%(objectname) %(objecttype) %(objectsize) %(rest)' | grep commit | awk '{print $1}'); do
|
|
|
|
# Get list of potentially binary files in this commit
|
|
mapfile -t binary_files < <(git log --diff-filter=d --pretty=format:%H -M100% --numstat ${commit}^! | grep -e "- - \w" | awk '{print $3}')
|
|
|
|
if [ ${#binary_files[@]} -eq 0 ]; then
|
|
continue
|
|
fi
|
|
|
|
# Check for override message
|
|
override=0
|
|
if git log --pretty=format:%B ${commit}^! | grep -qi "${commit_override_msg}"; then
|
|
override=1
|
|
fi
|
|
|
|
rejected_files=()
|
|
for file in "${binary_files[@]}"; do
|
|
# Check if it's an LFS pointer
|
|
# Use handle_pipefails as we may run into SIGPIPE error code
|
|
if git show "${commit}:${file}" | git lfs pointer --check --stdin || handle_pipefails $?; then
|
|
continue
|
|
fi
|
|
rejected_files+=("$file")
|
|
done
|
|
|
|
if [ ${#rejected_files[@]} -gt 0 ]; then
|
|
if [ "$override" -gt 0 ]; then
|
|
echo "Your push contains binary files but was accepted because of override commit message:"
|
|
else
|
|
status=1
|
|
echo "Your push was rejected because it contains binary files not tracked by Git LFS:"
|
|
fi
|
|
echo "Commit: $commit"
|
|
for file in "${rejected_files[@]}"; do
|
|
echo "File: $file"
|
|
done
|
|
fi
|
|
done
|
|
done
|
|
|
|
if [ "$status" -ne "0" ]; then
|
|
echo
|
|
echo "You must make sure that the binary files are tracked with Git LFS or seek help from the repo administrators."
|
|
echo "(Perhaps you did not setup Git LFS with 'git lfs install'?)"
|
|
echo
|
|
fi
|
|
exit $status
|