Last active
December 20, 2015 10:20
-
-
Save xkr47/10004875 to your computer and use it in GitHub Desktop.
How to validate the files being pushed to a remote Git repository and leave repository untouched if validation failed - works with bare and non-bare repos
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# This file should be installed in the remote repository as: | |
# - <path-to-bare-repo.git>/hooks/update if you have a bare repository | |
# - <path-to-regular-repo>/.git/hooks/update if you have a regular repository | |
set -e | |
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 | |
# In this example we only want to validate the master branch; if not, just exit if pushed branch is not master | |
if [ "${refname}" != "refs/heads/master" ]; then | |
exit 0 | |
fi | |
# In this example we want to forbid deleting the master branch | |
zero="0000000000000000000000000000000000000000" | |
if [ "${newrev}" = "$zero" ]; then | |
echo "Deletion of master branch is not supported" | |
exit 1 | |
fi | |
# convert to absolute path | |
export GIT_DIR="$(cd "$GIT_DIR" ; pwd)" | |
# check permissions | |
if [ ! -w $GIT_DIR/index ]; then echo "Permission denied - check file permissions in $GIT_DIR" ; exit 1 ; fi | |
# use separate index file and temporary checkout location when validating (for compatibility with non-bare repository - see https://gist.github.com/xkr47/8348709) | |
export GIT_INDEX_FILE="$GIT_DIR/hook-update-index" | |
export TMP_CHECKOUT="${GIT_INDEX_FILE}_dir/" | |
# make sure we clean up regardless of outcome | |
cleanup () { | |
set +e | |
rm -f "$GIT_INDEX_FILE" | |
rm -rf "$TMP_CHECKOUT" | |
} | |
trap cleanup EXIT | |
# checkout pushed revision to temporary directory and cd to that directory | |
git read-tree "${newrev}" | |
git checkout-index --prefix="${TMP_CHECKOUT}" -a | |
cd "${TMP_CHECKOUT}" | |
######################################################################### | |
######################################################################### | |
# | |
# Do the pre-push validation below - use "exit 1" to reject | |
# | |
######################################################################### | |
######################################################################### | |
# example: make sure we always have LICENSE.txt in the root of the project | |
if [ ! -e LICENSE.txt ]; then | |
echo LICENSE.txt missing | |
exit 1 | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See https://gist.github.com/xkr47/8348709 for how to set up non-bare remote repository, useful together with this