#!/bin/bash # # Copyright (c) 2010, Benjamin C. Meyer # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of the project nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ''AS IS'' AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # function hook_dirs { if [ ! -z "${1}" ] ; then hook="/${1}" else hook="" fi echo "${HOME}/.git_hooks${hook}" echo "${PWD}/git_hooks${hook}" echo "`git config hooks.global`"${hook} } function list_hooks_in_dir { find "${1}" -executable -type f 2>/dev/null | grep -v "^.$" | sort -V } function run_hooks { dir="${1}" if [[ -z ${dir} || ! -d "${dir}" ]] ; then echo "run_hooks requires a directory name as an argument." return 1 fi shift 1 for hook in `list_hooks_in_dir "${dir}"` do export last_run_hook="${hook} $@" if [ ! -z ${GIT_HOOKS_VERBOSE} ] ; then echo -n "@@ Running hook: " echo -n `basename \`dirname "${hook}"\`` echo "/`basename "${hook}"`" fi ${hook} "$@" done } function run_hook { set -e hook=`basename "${1}"` if [ -z ${hook} ] ; then echo "run requires a hook argument" return 1 fi shift 1 for dir in `hook_dirs "${hook}"`; do if [ ! -d "${dir}" ] ; then continue fi run_hooks "${dir}" "$@" done set +e } function install_hooks { GITDIR=`git rev-parse --git-dir` if [ ! $? -eq 0 ] ; then echo "$1 must be run inside a git repository" return 1 fi cd $GITDIR if [ "${1}" = "--install" ] ; then mv hooks hooks.old mkdir hooks cd hooks for file in applypatch-msg commit-msg post-applypatch post-checkout post-commit post-merge post-receive pre-applypatch pre-auto-gc pre-commit prepare-commit-msg pre-rebase pre-receive update do echo '#!/bin/bash git-hooks run "$0" "$@"' > "${file}" chmod +x "${file}" done else if [ ! -d hooks.old ] ; then echo "Error, hooks.old doesn't exists, aborting uninstall to not destroy something" return 1 fi rm -rf hooks mv hooks.old hooks fi } function list_hooks { while [ ! -d ".git" ] ; do cd .. done cat .git/hooks/pre-commit | grep 'git-hooks' > /dev/null 2> /dev/null if [ $? = 0 ] ; then echo -n "Git hooks ARE installed in this repository." else echo -n "Git hooks are NOT installed in this repository." fi echo ' Listing User, Project, and Global hooks:' echo '---' for dir in `hook_dirs`; do echo "${dir}:" for hook in `list_hooks_in_dir "${dir}"` ; do echo -n `basename \`dirname "${hook}"\`` echo -e "/`basename "${hook}"` \t- `${hook} --about`" done echo "" done } function report_error { echo "Hook failed: $last_run_hook" exit 1 } case $1 in run ) if [ ! -z "${GIT_DIR}" ] ; then unset GIT_DIR fi shift trap report_error ERR run_hook "$@" ;; --install|--uninstall ) install_hooks "$1" ;; -h|--help ) echo 'Git Hooks' echo '' echo 'Options:' echo ' --install Replace existing hooks in this repository with a call to' echo ' git hooks run [hook]. Move old hooks directory to hooks.old' echo ' --uninstall Remove existing hooks in this repository and rename hooks.old' echo ' back to hooks' echo " run [cmd] Run the hooks for cmd (such as pre-commit)" echo " (no arguments) Show currently installed hooks" ;; * ) list_hooks ;; esac