#!/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