2012-01-04 11 views
32

Jak wielu z was zapewne wie, w git może być tylko jeden typ haka. Jeśli konieczne jest dokonanie oceny dwóch haków aktualizacji. Git admin lewo z dwóch niewykonalna rozwiązań:Łańcuchowe haki gitów

  1. Merge skrypty przechwytujące razem
  2. Ręcznie łańcucha je z exec

szukam eleganckie rozwiązanie (napisany w bash) , coś w rodzaju folderu hooks/update.d lub hooks/post-receive.d, który pozwoli luźno powiązać oceny haków. Łańcuch powinien się zatrzymać, gdy tylko zawiedzie hak.

I rzeczywiście znaleziono akceptowalnego rozwiązania napisany w Perlu adresem URL http://blog.bluefeet.net/2011/08/chained-git-hooks

Problem: Mój serwer uruchamia różne wersje Perl i jestem coraz perllib niedopasowania wersji. To nie wyszło.

+1

pokrewne odpowiedź: http://stackoverflow.com/a/3464399/119963 Nacisk był na śledzenie haki, a nie ich łączenia, ale łańcuchowym jest w zasadzie banalna rozszerzenie: owinąć pętla dookoła wykonania haka (np. 'dla haka w hookach/update.d/*; do ...') – Cascabel

+0

Dziękuję za wskaźnik, pomogło –

Odpowiedz

32

Po dalszych badań i testów, tutaj jest roztwór roboczy:

utworzyć plik .git/hooks/hook-chain następująco

#!/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 

Teraz odwołuje żadnego haczyka, który wymaga łączenia, na przykład

  • ln - aktualizacja łańcucha haka
  • ln -s hak łańcuchowy po otrzymaniu

na koniec utwórz łańcuchy, zmieniając ich nazwę na 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 

na przykład, w powyższym przykładzie, hak zmiana uruchomi update.1acl następnie update.2github.

po otrzymywać hak z run post-receive.1email następnie post-receive.2github

+3

To nie jest strona z recenzowaniem kodu, ale .... raczej niż wyraźne usunięcie pliku tmp, usuń go automatycznie, dodając następujący wiersz przed wywołaniem mktemp: trap 'rm -f $ FILE' 0 –

+0

Dobra sugestia, dziękuję –

+1

W [tej wiadomości] (http://osdir.com/ ml/git/2009-01/msg00308.html), zamiast pliku tymczasowego ktoś robi 'dane = $ (cat)', a następnie 'echo" $ dane "| "$ hook" '. –

3

Dla tych, którzy nie są skłonni do klikania w każdym ogniwie w komentarzach below other answer, oto praktycznie niezmienionej wersji the script przez @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

stworzyłem skrypt w oparciu o pO i stanowisk Olivier Refalo (z pewnymi modyfikacjami):

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

Skrypt będzie generować pliki hak, który będzie wykonywać skrypty wewnątrz $hook_file_name.d/$hook_file_name.*

Na przykład: dla commit-msg hak, skrypt generują commit-msg plik pod .git/hooks że będzie wykonywał wszystkie skrypt pod commit-msg.d/.

Pliki pod numerem commit-msg.d powinny odpowiadać wzorowi commit-msg.*, aby umożliwić umieszczanie plików helper shell w tych folderach bez ich wykonywania. Wykorzystanie

Scenariusz: ./extend_git_hooks.sh [REPO_PATH]