2012-01-04 6 views
32

Như nhiều bạn có thể đã biết, chỉ có thể có một loại móc trong git. Nếu cần cập nhật hai móc cập nhật. Các admin git được trái với hai giải pháp không thể quản lý:Chaining git hooks

  1. Merge các script móc cùng
  2. thủ chuỗi chúng với một exec

Tôi đang tìm kiếm một giải pháp thanh lịch (viết bằng BASH) , giống như một thư mục hooks/update.d hoặc hooks/post-receive.d sẽ cho phép khớp nối lỏng lẻo các đánh giá móc. Các chuỗi phải dừng lại ngay sau khi một móc thất bại.

Tôi thực sự tìm thấy một giải pháp chấp nhận được viết bằng perl tại URL này http://blog.bluefeet.net/2011/08/chained-git-hooks

Vấn đề: máy chủ của tôi chạy phiên bản khác nhau của perl và tôi nhận được perllib sai lệch phiên bản. Nó thất bại.

+1

câu trả lời liên quan: http://stackoverflow.com/a/3464399/119963 Trọng tâm là có về theo dõi các móc, không chaining họ, nhưng về cơ bản chaining là một phần mở rộng tầm thường: quấn một vòng quanh thực thi móc (ví dụ 'móc trong móc/update.d/*; do ...') – Cascabel

+0

Cảm ơn bạn đã chọn con trỏ, nó đã giúp –

Trả lời

32

Sau khi điều tra và thử nghiệm hơn nữa, đây là một giải pháp làm việc:

tạo file .git/hooks/hook-chain như sau

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

Bây giờ liên kết bất kỳ móc mà đòi hỏi chaining, ví dụ

  • ln - s cập nhật chuỗi móc
  • ln -s móc chuỗi sau khi nhận

cuối cùng, tạo chuỗi bằng cách đổi tên chúng thành 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 

ví dụ, trong ví dụ trên, các cập nhật móc sẽ chạy update.1acl Tiếp theo update.2github.

Các hậu nhận móc với chạy hậu receive.1email Tiếp theo hậu receive.2github

+3

Đây không phải là trang đánh giá mã, mà là .... hơn explictly loại bỏ các tmpfile, loại bỏ nó tự động bằng cách thêm các dòng sau trước khi cuộc gọi đến mktemp: trap 'rm -f $ FILE' 0 –

+0

đề nghị tốt, cảm ơn bạn –

+1

Trong [mail] (http://osdir.com/ ml/git/2009-01/msg00308.html), thay vì tệp tạm thời, ai đó thực hiện 'data = $ (cat)' và sau đó 'echo" $ data "| "$ hook" '. –

3

Đối với những người không sẵn sàng bấm vào mỗi liên kết trong ý kiến ​​below other answer, đây là một phiên bản thực tế chưa sửa đổi của the script bởi @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

tôi tạo ra một kịch bản shell dựa trên OP và các bài viết Olivier Refalo (với một số sửa đổi):

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

Các kịch bản sẽ tạo ra một file móc rằng sẽ thực hiện các kịch bản bên trong $hook_file_name.d/$hook_file_name.*

Ví dụ: đối với commit-msg móc, kịch bản sẽ tạo ra commit-msg tập tin dưới .git/hooks rằng sẽ thực hiện tất cả các kịch bản dưới commit-msg.d/.

Tệp dưới commit-msg.d phải khớp với mẫu commit-msg.* để cho phép đặt tệp trình trợ giúp của trình bao trong thư mục đó mà không cần thực thi chúng.

Script sử dụng: ./extend_git_hooks.sh [REPO_PATH]