2010-08-05 36 views
48

Tôi muốn cảnh báo người dùng nếu thông điệp cam kết của họ không tuân theo một loạt các nguyên tắc nhất định và sau đó cung cấp cho họ tùy chọn chỉnh sửa thư cam kết của họ, bỏ qua cảnh báo hoặc hủy cam kết. Vấn đề là tôi dường như không có quyền truy cập vào stdin.Tôi làm cách nào để nhắc người dùng từ trong móc móc cam kết?

Dưới đây là tập tin cam-msg của tôi:

function verify_info { 
    if [ -z "$(grep '$2:.*[a-zA-Z]' $1)" ] 
    then 
     echo >&2 $2 information should not be omitted 
     local_editor=`git config --get core.editor` 
     if [ -z "${local_editor}" ] 
     then 
      local_editor=${EDITOR} 
     fi 
     echo "Do you want to" 
     select CHOICE in "edit the commit message" "ignore this warning" "cancel the commit"; do 
      case ${CHOICE} in 
       i*) echo "Warning ignored" 
        ;; 
       e*) ${local_editor} $1 
        verify_info "$1" $2 
        ;; 
       *) echo "CHOICE = ${CHOICE}" 
        exit 1 
        ;; 
      esac 
     done 
    fi 
} 

verify_info "$1" "Scope" 
if [ $# -ne 0 ]; 
then 
    exit $# 
fi 
verify_info "$1" "Affects" 
if [ $# -ne 0 ]; 
then 
    exit $# 
fi 

exit 0 

Đây là kết quả khi tôi rời khỏi thông tin Phạm vi trống:

Scope information should not be omitted 
Do you want to: 
1) edit the commit message 3) cancel the commit 
2) ignore this warning 
#? 

Thông điệp là chính xác, nhưng nó không thực sự dừng lại cho đầu vào. Tôi cũng đã thử sử dụng lệnh "read" đơn giản hơn và nó cũng có cùng một vấn đề. Dường như vấn đề là tại thời điểm này git có quyền kiểm soát stdin và đang cung cấp đầu vào của riêng nó. Làm thế nào để sửa lỗi này?

Cập nhật: Có vẻ như đây có thể là bản sao của this question mà không may dường như cho thấy tôi không may mắn.

+0

Khi bạn có quyền truy cập vào X Server, bạn có thể thoát sang công cụ hộp thoại đồ họa. Xấu xí nhưng hoạt động – Rudi

+0

Thay vì thông báo lỗi, bạn có thể chỉ cần cung cấp một thông báo lỗi thông tin - bao gồm việc lặp lại lệnh cần thiết để bỏ qua cảnh báo. – bstpierre

+0

@btspierre, đó là cách tiếp cận mà tôi đã kết thúc. Theo lời khuyên của John Feminella, tôi cho phép sử dụng một biến môi trường để ghi đè cảnh báo và chỉ lặp lại cảnh báo khi gặp phải tình huống xấu. –

Trả lời

108

Gọi số exec < /dev/tty gán đầu vào chuẩn cho bàn phím. Làm việc cho tôi trong một cam kết bài móc git:

#!/bin/sh 

echo "[post-commit hook] Commit done!" 

# Allows us to read user input below, assigns stdin to keyboard 
exec < /dev/tty 

while true; do 
    read -p "[post-commit hook] Check for outdated gems? (Y/n) " yn 
    if [ "$yn" = "" ]; then 
    yn='Y' 
    fi 
    case $yn in 
     [Yy]) bundle outdated --pre; break;; 
     [Nn]) exit;; 
     *) echo "Please answer y or n for yes or no.";; 
    esac 
done 
+13

STDIN có thể được đóng lại bằng 'exec <& -' – Andy

+10

Nếu bạn đang sử dụng Ruby, hãy dịch sang 'STDIN.reopen ('/ dev/tty')'. Những thứ tuyệt vời, đây là câu trả lời thực sự. –

+2

Điều này thật tuyệt vời, nhưng nó có thể bị phá vỡ khi cam kết từ một công cụ khác, chẳng hạn như một trình soạn thảo. Không chắc chắn làm thế nào để có được xung quanh đó, nhưng nếu ai đó có một ý tưởng, tôi muốn được quan tâm để nghe. – Peeja

4

Móc cam kết không chạy trong môi trường tương tác (như bạn đã nhận thấy).

Cách duy nhất để thông báo đáng tin cậy cho người dùng là viết một lỗi để stdout, đặt một bản sao của thư cam kết trong tệp 'BAD_MSG' và hướng dẫn người dùng chỉnh sửa tệp và 'git commit --file = BAD_MSG'


Nếu bạn có một số kiểm soát đối với môi trường bạn có thể có một trình soạn thảo thay thế đó là một kịch bản wrapper để kiểm tra được thông báo đề xuất, và có thể khởi động lại trình biên tập với một thông báo nhận xét thêm.

Về cơ bản, bạn chạy trình chỉnh sửa, kiểm tra tệp được lưu dựa vào quy tắc của bạn. và nếu không thành công, hãy thêm thông báo cảnh báo của bạn (có hàng đầu #) vào tệp và khởi động lại trình chỉnh sửa.

Bạn thậm chí có thể cho phép họ đặt trong dòng '# FORCE = true' trong thông báo sẽ chặn kiểm tra và tiếp tục.

+3

Hãy thử gọi 'exec

+0

Mặc dù đây là một câu trả lời đúng đắn, nhưng Eliot nên được chấp nhận khi chứng minh nó * là * thực sự có thể! –

+0

Người dùng có thể bỏ qua móc bằng '--no-verify', không cần phải sử dụng' # FORCE = true' hackery. – fsaintjacques

1

Để làm select cửa cho đầu vào, bạn cũng có thể cố gắng chuyển hướng stdin của select từ /dev/fd/3 (Xem: Read input in bash inside a while loop).

# sample code using a while loop to simulate git consuming stdin 
{ 
echo 'fd 0' | while read -r stdin; do 
    echo "stdin: $stdin" 
    echo "Do you want to" 
    select CHOICE in "edit the commit message" "ignore this warning" "cancel the commit"; do 
     case ${CHOICE} in 
     i*) echo "Warning ignored" 
      ;; 
     e*) echo ${local_editor} $1 
      echo verify_info "$1" $2 
      ;; 
     *) echo "CHOICE = ${CHOICE}" 
      exit 1 
      ;; 
     esac 
    done 0<&3 3<&- 
done 
} 3<&- 3<&0 
0

hoạt động tốt khi chạy lệnh git commit từ dòng lệnh. Trên cửa sổ (chưa thử trên Linux) nếu bạn sử dụng gitk hoặc git-gui, bạn sẽ không thể nhắc vì bạn gặp lỗi trên dòng "exec </dev/tty".

Các sollution là để gọi git-bash.exe trong móc của bạn:

.git/móc/post-cam chứa:

#!/bin/sh 
exec /c/Program\ Files/Git/git-bash.exe /path/to/my_repo/.git/hooks/post-checkout.sh 

các .git/móc/post-cam.sh tệp chứa:

# -------------------------------------------------------- 
# usage: f_askContinue "my question ?" 
function f_askContinue { 
    local myQuestion=$1 

    while true; do 
    read -p "${myQuestion} " -n 1 -r answer 
    case $answer in 
     [Yy]*) printf "\nOK\n"; break;; 
     [Nn]*) printf "\nAbandon\n"; 
        exit;; 
     *) printf "\nAnswer with Yes or No.\n";; 
    esac 
    done 
} 

f_askContinue "Do you want to continue ?" 
echo "This command is executed after the prompt !" 
Các vấn đề liên quan