Chaining git hooks

余生颓废 提交于 2019-11-28 16:00:53

问题


As many of you probably know, there can be only one hook type in git. If two update hooks need to be evaluated. The git admin is left with two unmanageable solutions:

  1. Merge the hook scripts together
  2. Manually chain them with an exec

I am looking for an elegant solution (written in BASH),something like a folder hooks/update.d or hooks/post-receive.d that will allow the loosely coupling of hook evaluations. The chaining should stop as soon as a hook fails.

I actually found an acceptable solution written in perl at this URL http://blog.bluefeet.net/2011/08/chained-git-hooks

The problem: my server runs different versions of perl and I am getting perllib version mismatches. It fails.


回答1:


After further investigation and testing, here is a working solution:

create file .git/hooks/hook-chain as follows

#!/bin/bash
#
# author: orefalo

hookname=`basename $0`


FILE=`mktemp`
trap 'rm -f $FILE' EXIT
cat - > $FILE

for hook in $GIT_DIR/hooks/$hookname.*
do
    if test -x "$hook"; then
#       echo $hook
        cat $FILE | $hook "$@"
        status=$?

        if test $status -ne 0; then
            echo Hook $hook failed with error code $status
            exit $status
        fi
    fi
done

Now link any hook that requires chaining, for instance

  • ln -s hook-chain update
  • ln -s hook-chain post-receive

finally, create the chains by renaming them as hookname.action

 -rwxr-xr-x. 1 git  git  6710  functions
 -rwxr-xr-x. 1 git  git   280  hook-chain
 -rwxr-xr-x. 1 git  git  1524  post-mirror
 lrwxrwxrwx. 1 root root   10  post-receive -> hook-chain
 -rwxr-xr-x. 1 git  git  8763  post-receive.1email
 -rwxr-xr-x. 1 git  git  1745  post-receive.2github
 -rwxr-xr-x. 1 git  git   473  post-upload-pack
 -rwxr-xr-x. 1 git  git   346  pre-receive
 lrwxrwxrwx. 1 root root   10  update -> hook-chain
 -rwxr-xr-x. 1 git  git  2975  update.1acl
 -rwxr-xr-x. 1 git  git   328  update.2github

for instance, in the sample above, the update hook will run update.1acl followed by update.2github.

The post-receive hook with run post-receive.1email followed by post-receive.2github




回答2:


For those who're not willing to click on every link in comments below other answer, here's a practically unmodified version of the script by @HenrikN:

#!/bin/bash

# Runs all executable hookname-* hooks and exits after,
# if any of them was not successful.
#
# Based on
# http://osdir.com/ml/git/2009-01/msg00308.html

data=$(cat)
exitcodes=()
hookname=$(basename $0)

# Run each hook, passing through STDIN and storing the exit code.
# We don't want to bail at the first failure, as the user might
# then bypass the hooks without knowing about additional issues.

for hook in $GIT_DIR/hooks/$hookname-*; do
  test -x "$hook" || continue
  echo "$data" | "$hook"
  exitcodes+=($?)
done

# If any exit code isn't 0, bail.

for i in "${exitcodes[@]}"; do
  [ "$i" == 0 ] || exit $i
done



回答3:


I created a shell script based on OP and Olivier Refalo posts (with some modifications):

https://gist.github.com/amirbawab/e9f42ef8d441316707d9b90777e5718b

The script will generate a hook files that will execute scripts inside $hook_file_name.d/$hook_file_name.*

For example: for commit-msg hook, the script will generate commit-msg file under .git/hooks that will execute all script under commit-msg.d/.

Files under commit-msg.d should match the pattern commit-msg.* to allow placing helper shell files in those folder without executing them.

Script usage: ./extend_git_hooks.sh [REPO_PATH]



来源:https://stackoverflow.com/questions/8730514/chaining-git-hooks

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!