#!/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}" GITDIR=`git rev-parse --git-dir` cd $GITDIR/.. echo "${PWD}/git_hooks${hook}" echo "${PWD}/.githooks${hook}" eval echo "`git config hooks.global`"${hook} } function list_hooks_in_dir { if [ $OSTYPE = "darwin10.0" ] ; then find "${1}/" -executable -type f 2>/dev/null | grep -v "^.$" | sort else find "${1}/" -executable -type f 2>/dev/null | grep -v "^.$" | sort -V fi } 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 { GITDIR=`git rev-parse --git-dir` cat $GITDIR/hooks/pre-commit 2> /dev/null | grep 'git-hooks' > /dev/null 2> /dev/null if [ $? = 0 ] ; then echo "Git hooks ARE installed in this repository." echo "" else echo "Git hooks are NOT installed in this repository." echo "" 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