2012-01-04 15 views
32

Como muchos de ustedes probablemente saben, solo puede haber un tipo de gancho en git. Si es necesario evaluar dos ganchos de actualización. El administrador git se queda con dos soluciones inmanejables:Encadenamiento de ganchos git

  1. fusionar los ficheros de ganchos juntos
  2. encadenarlos manualmente con un exec

Busco a una solución elegante (escrito en Bash) , algo así como una carpeta hooks/update.d o hooks/post-receive.d que permitirá el acoplamiento flexible de las evaluaciones de ganchos. El encadenamiento debe detenerse tan pronto como un gancho falle.

realidad he encontrado una solución aceptable escrito en Perl en esta dirección URL http://blog.bluefeet.net/2011/08/chained-git-hooks

El problema: mi servidor ejecuta diferentes versiones de Perl y estoy consiguiendo perllib conflictos de versiones. Falla.

+1

respuesta relacionada: http://stackoverflow.com/a/3464399/119963 El enfoque no estaba en el seguimiento de los ganchos, no encadenándolos, pero el encadenamiento es básicamente una extensión trivial: envolver una bucle alrededor de la ejecución del gancho (por ejemplo, 'para el gancho en los ganchos/update.d/*; do ...') – Cascabel

+0

Gracias por el puntero, me ayudó –

Respuesta

32

Después de más investigación y pruebas, aquí es una solución de trabajo:

crear el archivo .git/hooks/hook-chain de la siguiente manera

#!/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 "[email protected]" 
     status=$? 

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

Ahora vincular cualquier gancho que requiere encadenamiento, por ejemplo

  • ln - s actualización de la cadena de gancho
  • ln -s cadena de gancho post-recepción

finalmente, cree las cadenas renombrándolas como 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 

por ejemplo, en el ejemplo anterior, la actualización gancho se ejecutará update.1acl seguido de update.2github.

El posterior a recibir el gancho con plazo post-receive.1email seguido por post-receive.2github

+3

Este no es un sitio de revisión de código, sino ... más bien que eliminar explícitamente el archivo tmp, elimínelo automáticamente agregando la siguiente línea antes de la llamada a mktemp: trap 'rm -f $ FILE' 0 –

+0

buena sugerencia, gracias –

+1

En [este correo] (http://osdir.com/ ml/git/2009-01/msg00308.html), en lugar de un archivo temporal alguien hace 'data = $ (cat)' y luego 'echo" $ datos "| "$ hook" '. –

3

Para aquellos que no están dispuestos a hacer clic en cada enlace en los comentarios below other answer, aquí está una versión prácticamente no modificada de the script por @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 
0

I creó una secuencia de comandos shell basado en OP y mensajes Olivier Refalo (con algunas modificaciones):

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

El script generará un archivos de gancho que se ejecutarán los scripts dentro $hook_file_name.d/$hook_file_name.*

Por ejemplo: commit-msg gancho, la secuencia de comandos generará commit-msg archivo bajo .git/hooks que ejecutará todas guión bajo commit-msg.d/.

Los archivos en commit-msg.d deben coincidir con el patrón commit-msg.* para permitir la colocación de archivos auxiliares en esa carpeta sin ejecutarlos. el uso

Guión: ./extend_git_hooks.sh [REPO_PATH]