Before, the hook would allow pushing binary files to newly created empty repos. Now we handle and test this in our test suite.
112 lines
3.4 KiB
Bash
Executable File
112 lines
3.4 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
|
|
|
|
if [ "$oldrev" = "$nullsha" ]; then
|
|
if [ $(git rev-parse HEAD) = "HEAD" ]; then
|
|
# Iterate over all commits if there is no HEAD.
|
|
# This happens when the repo has just been initalized
|
|
rev_range=${newrev}
|
|
else
|
|
# Don't iterate over any commits already in the default branch of the repo
|
|
rev_range=HEAD..${newrev}
|
|
fi
|
|
else
|
|
rev_range=${oldrev}..${newrev}
|
|
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 ${rev_range} |
|
|
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}^! |
|
|
awk -F'\t' '$1=="-" && $2=="-" {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
|
|
if [[ $file == *" => "* ]]; then
|
|
# If the name contains " => " then this probably means the file was moved.
|
|
# If it was just moved, then it must still be a binary file.
|
|
rejected_files+=("$file")
|
|
continue
|
|
fi
|
|
# 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
|