Git Hooks: Merge hook scripts and tests from blender-devops

This commit is contained in:
Bart van der Braak
2025-12-18 11:44:03 +01:00
parent 620838eea7
commit 053119419c
16 changed files with 691 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
# Run single test provided via $1.
# Prints "ok" on success, "FAIL" on failure, and returns the appropriate status code.
run_test() {
local TEST_SCRIPT=$1
printf '%s' "Running $(basename "${TEST_SCRIPT}")... "
# Run test silently.
# Return 0 on success, 1 on failure.
if "${TEST_SCRIPT}" > /dev/null 2>&1; then
echo "ok"
return 0
else
echo "FAIL"
return 1
fi
}
# Run all tests in the given directory (specified as $1).
# All .sh tests are executed in sorted order.
# The script reports how many tests failed and exits with non-zero status if any did.
run_tests_in_directory() {
local DIR=$1
local failed=0
echo "== Running tests in directory $(basename "${DIR}") =="
# Iterate over all .sh files and run them one by one.
for test_script in $(ls "${DIR}" | sort); do
case "${test_script}" in
*.sh)
if ! run_test "${DIR}/${test_script}"; then
failed=$((failed + 1))
fi
;;
esac
done
# After running all tests, report overall result.
if [ "$failed" -ne 0 ]; then
echo "$failed test(s) failed."
exit 1
else
echo "All tests passed."
fi
}

View File

@@ -0,0 +1,31 @@
#!/bin/sh
# Test: create text file in the empty repository and try to push it.
#
# It is expected to pass as it is perfectly nomial usage of Git for text
# based files.
set -e
SCRIPT=$(readlink -f "$0")
SCRIPT_PATH=$(dirname "$SCRIPT")
. ${SCRIPT_PATH}/functions
setup_temp_git_identity
ORIGIN_REPO_DIR=`setup_bare_origin_repository`
WORK_GIT_DIR=`clone_repository "${ORIGIN_REPO_DIR}"`
install_hook "${ORIGIN_REPO_DIR}" "${SCRIPT_PATH}/../../deny-binary" "pre-receive"
echo "Hello, World!" > "${WORK_GIT_DIR}/README.txt"
git -C "${WORK_GIT_DIR}" add README.txt
git -C "${WORK_GIT_DIR}" commit --message "Initial commit"
if ! git -C "${WORK_GIT_DIR}" push; then
exit 1
fi
echo
echo "Test passed!"
exit 0

View File

@@ -0,0 +1,38 @@
#!/bin/sh
# Test: add text file to the existing repository and try to push it.
#
# It is expected to pass as it is perfectly nomial usage of Git for text
# based files.
set -e
SCRIPT=$(readlink -f "$0")
SCRIPT_PATH=$(dirname "$SCRIPT")
. ${SCRIPT_PATH}/functions
setup_temp_git_identity
ORIGIN_REPO_DIR=`setup_bare_origin_repository`
WORK_GIT_DIR=`clone_repository "${ORIGIN_REPO_DIR}"`
install_hook "${ORIGIN_REPO_DIR}" "${SCRIPT_PATH}/../../deny-binary" "pre-receive"
echo "Hello, World!" > "${WORK_GIT_DIR}/README.txt"
git -C "${WORK_GIT_DIR}" add README.txt
git -C "${WORK_GIT_DIR}" commit --message "Initial commit"
if ! git -C "${WORK_GIT_DIR}" push; then
exit 1
fi
echo "Hello, World!" > "${WORK_GIT_DIR}/NOTES.txt"
git -C "${WORK_GIT_DIR}" add NOTES.txt
git -C "${WORK_GIT_DIR}" commit --message "Add file"
if ! git -C "${WORK_GIT_DIR}" push; then
exit 1
fi
echo
echo "Test passed!"
exit 0

View File

@@ -0,0 +1,32 @@
#!/bin/sh
# Test: Add binary file to an empty repository and try to push.
#
# It is expected to pass as part of a logic which allows to branch off
# existing branches where it is possible to have binary files that were
# added prior to migration to Git LFS.
set -e
SCRIPT=$(readlink -f "$0")
SCRIPT_PATH=$(dirname "$SCRIPT")
. ${SCRIPT_PATH}/functions
setup_temp_git_identity
ORIGIN_REPO_DIR=`setup_bare_origin_repository`
WORK_GIT_DIR=`clone_repository "${ORIGIN_REPO_DIR}"`
install_hook "${ORIGIN_REPO_DIR}" "${SCRIPT_PATH}/../../deny-binary" "pre-receive"
dd if=/dev/zero of="${WORK_GIT_DIR}/data.bin" bs=1 count=32k
git -C "${WORK_GIT_DIR}" add data.bin
git -C "${WORK_GIT_DIR}" commit --message "Initial commit"
if ! git -C "${WORK_GIT_DIR}" push; then
exit 1
fi
echo
echo "Test passed!"
exit 0

View File

@@ -0,0 +1,38 @@
#!/bin/sh
# Test: add binary file to the existing repository and try to push it.
#
# This test is expected to fail as new binary files are expected to be
# using Git LFS.
set -e
SCRIPT=$(readlink -f "$0")
SCRIPT_PATH=$(dirname "$SCRIPT")
. ${SCRIPT_PATH}/functions
setup_temp_git_identity
ORIGIN_REPO_DIR=`setup_bare_origin_repository`
WORK_GIT_DIR=`clone_repository "${ORIGIN_REPO_DIR}"`
install_hook "${ORIGIN_REPO_DIR}" "${SCRIPT_PATH}/../../deny-binary" "pre-receive"
echo "Hello, World!" > "${WORK_GIT_DIR}/README.txt"
git -C "${WORK_GIT_DIR}" add README.txt
git -C "${WORK_GIT_DIR}" commit --message "Initial commit"
if ! git -C "${WORK_GIT_DIR}" push; then
exit 1
fi
dd if=/dev/zero of="${WORK_GIT_DIR}/data.bin" bs=1 count=32k
git -C "${WORK_GIT_DIR}" add data.bin
git -C "${WORK_GIT_DIR}" commit --message "Add binary file"
if git -C "${WORK_GIT_DIR}" push; then
exit 1
fi
echo
echo "Test passed!"
exit 0

View File

@@ -0,0 +1,41 @@
#!/bin/sh
# Test: add binary file that starts with Git LFS reference content.
#
# This test is expected to fail as it is actually a binary file.
set -e
SCRIPT=$(readlink -f "$0")
SCRIPT_PATH=$(dirname "$SCRIPT")
. ${SCRIPT_PATH}/functions
setup_temp_git_identity
ORIGIN_REPO_DIR=`setup_bare_origin_repository`
WORK_GIT_DIR=`clone_repository "${ORIGIN_REPO_DIR}"`
install_hook "${ORIGIN_REPO_DIR}" "${SCRIPT_PATH}/../../deny-binary" "pre-receive"
echo "Hello, World!" > "${WORK_GIT_DIR}/README.txt"
git -C "${WORK_GIT_DIR}" add README.txt
git -C "${WORK_GIT_DIR}" commit --message "Initial commit"
if ! git -C "${WORK_GIT_DIR}" push; then
exit 1
fi
echo "version https://git-lfs.github.com/spec/v1" > "${WORK_GIT_DIR}/data.bin"
echo "oid sha256:c35020473aed1b4642cd726cad727b63fff2824ad68cedd7ffb73c7cbd890479" >> "${WORK_GIT_DIR}/data.bin"
echo "size 32768" >> "${WORK_GIT_DIR}/data.bin"
dd if=/dev/zero of="${WORK_GIT_DIR}/data.bin" bs=1 count=32k oflag=append conv=notrunc
git -C "${WORK_GIT_DIR}" add data.bin
git -C "${WORK_GIT_DIR}" commit --message "Add binary file"
if git -C "${WORK_GIT_DIR}" push; then
exit 1
fi
echo
echo "Test passed!"
exit 0

View File

@@ -0,0 +1,46 @@
#!/bin/sh
# Test: add binary file to the existing repository with proper LFS filters
# installed prior to adding a binary file.
#
# This test is expected to pass as it is an expected usage of Git LFS.
set -e
SCRIPT=$(readlink -f "$0")
SCRIPT_PATH=$(dirname "$SCRIPT")
. ${SCRIPT_PATH}/functions
setup_temp_git_identity
ORIGIN_REPO_DIR=`setup_bare_origin_repository`
WORK_GIT_DIR=`clone_repository "${ORIGIN_REPO_DIR}"`
install_hook "${ORIGIN_REPO_DIR}" "${SCRIPT_PATH}/../../deny-binary" "pre-receive"
echo "Hello, World!" > "${WORK_GIT_DIR}/README.txt"
git -C "${WORK_GIT_DIR}" add README.txt
git -C "${WORK_GIT_DIR}" commit --message "Initial commit"
if ! git -C "${WORK_GIT_DIR}" push; then
exit 1
fi
git -C "${WORK_GIT_DIR}" lfs install
git -C "${WORK_GIT_DIR}" lfs track "*.bin"
git -C "${WORK_GIT_DIR}" add .gitattributes
git -C "${WORK_GIT_DIR}" commit --message "Track .bin files with Git LFS"
if ! git -C "${WORK_GIT_DIR}" push; then
exit 1
fi
dd if=/dev/zero of="${WORK_GIT_DIR}/data.bin" bs=1 count=32k
git -C "${WORK_GIT_DIR}" add data.bin
git -C "${WORK_GIT_DIR}" commit --message "Add binary file"
if ! git -C "${WORK_GIT_DIR}" push; then
exit 1
fi
echo
echo "Test passed!"
exit 0

View File

@@ -0,0 +1,47 @@
#!/bin/sh
# Test: add binary file to the existing repository before LFS filters is
# configured, configure filter, and convert to LFS.
#
# This test is expected to fail as all new files after adding filter are
# supposed to be covered by Git LFS.
set -e
SCRIPT=$(readlink -f "$0")
SCRIPT_PATH=$(dirname "$SCRIPT")
. ${SCRIPT_PATH}/functions
setup_temp_git_identity
ORIGIN_REPO_DIR=`setup_bare_origin_repository`
WORK_GIT_DIR=`clone_repository "${ORIGIN_REPO_DIR}"`
install_hook "${ORIGIN_REPO_DIR}" "${SCRIPT_PATH}/../../deny-binary" "pre-receive"
echo "Hello, World!" > "${WORK_GIT_DIR}/README.txt"
git -C "${WORK_GIT_DIR}" add README.txt
git -C "${WORK_GIT_DIR}" commit --message "Initial commit"
if ! git -C "${WORK_GIT_DIR}" push; then
exit 1
fi
dd if=/dev/zero of="${WORK_GIT_DIR}/data.bin" bs=1 count=32k
git -C "${WORK_GIT_DIR}" add data.bin
git -C "${WORK_GIT_DIR}" commit --message "Add binary file"
git -C "${WORK_GIT_DIR}" lfs install
git -C "${WORK_GIT_DIR}" lfs track "*.bin"
git -C "${WORK_GIT_DIR}" add .gitattributes
git -C "${WORK_GIT_DIR}" commit --message "Track .bin files with Git LFS"
git -C "${WORK_GIT_DIR}" lfs migrate import --no-rewrite --yes data.bin
if git -C "${WORK_GIT_DIR}" push; then
exit 1
fi
echo
echo "Test passed!"
exit 0

View File

@@ -0,0 +1,53 @@
#!/bin/sh
# Test: Add filter and convert binary file to LFS on an existing repository.
#
# This test is expected to pass since it is perfectly nominal operation to do
# when dealing with legacy code base where binary files were added before LFS
# was configured, and when conversion is needed after the install of the deny
# hook.
set -e
SCRIPT=$(readlink -f "$0")
SCRIPT_PATH=$(dirname "$SCRIPT")
. ${SCRIPT_PATH}/functions
setup_temp_git_identity
ORIGIN_REPO_DIR=`setup_bare_origin_repository`
WORK_GIT_DIR=`clone_repository "${ORIGIN_REPO_DIR}"`
echo "Hello, World!" > "${WORK_GIT_DIR}/README.txt"
git -C "${WORK_GIT_DIR}" add README.txt
git -C "${WORK_GIT_DIR}" commit --message "Initial commit"
if ! git -C "${WORK_GIT_DIR}" push; then
exit 1
fi
dd if=/dev/zero of="${WORK_GIT_DIR}/data.bin" bs=1 count=32k
git -C "${WORK_GIT_DIR}" add data.bin
git -C "${WORK_GIT_DIR}" commit --message "Add binary file"
if ! git -C "${WORK_GIT_DIR}" push; then
exit 1
fi
install_hook "${ORIGIN_REPO_DIR}" "${SCRIPT_PATH}/../../deny-binary" "pre-receive"
git -C "${WORK_GIT_DIR}" lfs install
git -C "${WORK_GIT_DIR}" lfs track "*.bin"
git -C "${WORK_GIT_DIR}" add .gitattributes
git -C "${WORK_GIT_DIR}" commit --message "Track .bin files with Git LFS"
git -C "${WORK_GIT_DIR}" lfs migrate import --no-rewrite --yes data.bin
git -C "${WORK_GIT_DIR}" reset --soft HEAD~1
git -C "${WORK_GIT_DIR}" commit --amend --message "Track .bin files with Git LFS and convert existing file"
if ! git -C "${WORK_GIT_DIR}" push; then
exit 1
fi
echo
echo "Test passed!"
exit 0

View File

@@ -0,0 +1,47 @@
# Set up temp Git identity if none is set
setup_temp_git_identity() {
export GIT_AUTHOR_NAME="Test User"
export GIT_AUTHOR_EMAIL="tests@example.com"
export GIT_COMMITTER_NAME="Test User"
export GIT_COMMITTER_EMAIL="tests@example.com"
}
# Get temporary directory where test data will be generated.
# The function echo's the directory.
get_tmp_dir() {
local SCRIPT=$(readlink -f "$0")
local SCRIPT_PATH=$(dirname "$SCRIPT")
echo "$(dirname ${0})/tmp/$(basename "${SCRIPT%.*}")"
}
# Setup bare repository which could be used as a server-side upstream.
# The function echo's the path to the repository.
setup_bare_origin_repository() {
local TMP_DIR=`get_tmp_dir`
local REPO_DIR="${TMP_DIR}/origin/test-repo.git"
rm -rf "${REPO_DIR}"
mkdir -p "${REPO_DIR}"
git -C "${REPO_DIR}" init --bare --initial-branch=main > /dev/null 2>&1
echo "${REPO_DIR}"
}
# Install hook to the given bare repository.
# The bare git repository is provided as $1, hook script is provided as $2,
# and the hook name is provided as $3.
install_hook() {
local GIT_DIR="${1}"
local HOOK_SCRIPT="${2}"
local HOOK_NAME="${3}"
cp "${HOOK_SCRIPT}" "${GIT_DIR}/hooks/${HOOK_NAME}"
}
# Clone repository provided via $1. The path to the working directory is
# echo'd.
clone_repository() {
local TMP_DIR=`get_tmp_dir`
local WORK_GIT_DIR="${TMP_DIR}/checkout/test-repo"
rm -rf "${WORK_GIT_DIR}"
git clone "${1}" "${WORK_GIT_DIR}" > /dev/null 2>&1
echo "${WORK_GIT_DIR}"
}

View File

@@ -0,0 +1,10 @@
#!/bin/sh
set -e
SCRIPT=$(readlink -f "$0")
SCRIPT_PATH=$(dirname "$SCRIPT")
. "${SCRIPT_PATH}/common/functions"
run_tests_in_directory "${SCRIPT_PATH}/deny_binary"