2010-08-05 12 views
48

मैं उपयोगकर्ता को चेतावनी देना चाहता हूं कि उनका प्रतिबद्ध संदेश दिशानिर्देशों के एक निश्चित समूह का पालन नहीं करता है, और फिर उन्हें अपने प्रतिबद्ध संदेश को संपादित करने, चेतावनी को अनदेखा करने या प्रतिबद्धता को रद्द करने का विकल्प देता है। समस्या यह है कि मुझे लगता है कि मुझे stdin तक पहुंच नहीं है।मैं उपयोगकर्ता को प्रतिबद्ध-संदेश हुक के भीतर से कैसे संकेत दूं?

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 

यहाँ उत्पादन जब मैं खाली स्कोप जानकारी छोड़ दें:

नीचे मेरी प्रतिबद्ध-msg फ़ाइल है

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

संदेश सही है, लेकिन यह वास्तव में नहीं रुकती इनपुट के लिए। मैंने सरल "पढ़ने" कमांड का उपयोग करने का भी प्रयास किया है, और यह एक ही समस्या है। ऐसा लगता है कि समस्या यह है कि इस बिंदु पर गिट के पास स्टडीन का नियंत्रण होता है और यह अपना इनपुट प्रदान कर रहा है। मैं यह कैसे तय करुं?

अद्यतन: ऐसा लगता है कि यह this question का डुप्लिकेट हो सकता है जो दुर्भाग्य से लगता है कि मैं भाग्य से बाहर हूं।

+0

जब आपके पास एक्स सर्वर तक पहुंच है तो आप एक आलेखीय संवाद उपकरण से बच सकते हैं। बदसूरत-लेकिन-काम – Rudi

+0

त्रुटि संदेश के बजाय आप केवल एक सूचनात्मक त्रुटि संदेश प्रदान कर सकते हैं - जिसमें चेतावनी को अनदेखा करने के लिए आवश्यक कमांड को प्रतिबिंबित करना शामिल है। – bstpierre

+0

@btspierre, यही वह दृष्टिकोण है जिसे मैंने उठाया। जॉन फेमिनेला की सलाह पर, मैंने चेतावनी को ओवरराइड करने के लिए पर्यावरण चर के उपयोग की अनुमति दी, और जब भी खराब स्थिति का सामना किया जाता है तो चेतावनी को प्रतिबिंबित करें। –

उत्तर

108

कॉलिंग exec < /dev/tty कीबोर्ड पर मानक इनपुट असाइन करता है। एक के बाद प्रतिबद्ध 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

एसटीडीआईएन को फिर से बंद कर दिया जा सकता है 'exec <& - ' – Andy

+10

यदि आप रूबी का उपयोग कर रहे हैं, तो यह' STDIN.reopen ('/ dev/tty') में अनुवाद करेगा। बहुत बढ़िया सामान, यह असली जवाब है। –

+2

यह कमाल है, लेकिन यह एक संपादक जैसे किसी अन्य उपकरण से काम करते समय तोड़ सकता है। सुनिश्चित नहीं है कि इसके आसपास कैसे जाना है, लेकिन अगर किसी के पास कोई विचार है, तो मुझे सुनने में दिलचस्पी होगी। – Peeja

4

प्रतिबद्ध-संदेश हुक एक इंटरैक्टिव वातावरण में नहीं चलाया जाता है (जैसा कि आपने देखा है)।

विश्वसनीय सूचित करने का एकमात्र तरीका उपयोगकर्ता को सूचित करने के लिए एक त्रुटि लिखना होगा, 'BAD_MSG' फ़ाइल में प्रतिबद्ध संदेश की एक प्रति रखें और उपयोगकर्ता को फ़ाइल को संपादित करने और 'git commit --file = BAD_MSG '


आप पर्यावरण पर कुछ नियंत्रण है, तो आप एक वैकल्पिक संपादक जो एक आवरण स्क्रिप्ट है कि प्रस्तावित संदेश की जाँच करता है, और एक अतिरिक्त टिप्पणी की संदेश के साथ संपादक पुनः आरंभ कर सकते है हो सकता था।

असल में, आप संपादक चलाते हैं, अपने नियमों के विरुद्ध सहेजी गई फ़ाइल की जांच करें। और यदि यह विफल हो जाता है, तो फ़ाइल में अपने चेतावनी संदेश (अग्रणी # के साथ) को प्रीपेड करें और संपादक को पुनरारंभ करें।

आप उन्हें संदेश में '# FORCE = true' पंक्ति में रखने की अनुमति भी दे सकते हैं जो चेक को दबाए रखेगा और जारी रखेगा।

+3

उपयोगकर्ता इनपुट को कैप्चर करने में सक्षम होने के लिए पहले 'exec

+0

हालांकि यह एक अच्छा विचार है, एलियट को स्वीकार किया जाना चाहिए क्योंकि वह यह साबित करता है * वास्तव में संभव है! –

+0

उपयोगकर्ता '--no-verify' के साथ हुक छोड़ सकता है, '# FORCE = true' हैकर पर रिसॉर्ट करने की आवश्यकता है। – fsaintjacques

1

इनपुट के लिए select बंद करने के लिए, आप भी /dev/fd/3 (: Read input in bash inside a while loop देखें) से select की stdin रीडायरेक्ट करने के लिए कोशिश कर सकते हैं।

# 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

कमांड लाइन से गिट प्रतिबद्ध चलाने पर यह ठीक काम करता है। विंडोज़ पर (लिनक्स पर कोशिश नहीं की गई है) यदि आप गिटक या गिट-गुई का उपयोग करते हैं तो आप संकेत नहीं दे पाएंगे क्योंकि आपको "exec </dev/tty" लाइन पर कोई त्रुटि मिलती है।

sollution अपने हुक में Git-bash.exe कॉल करने के लिए है:

.git/हुक/उत्तर प्रतिबद्ध शामिल हैं:

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

.git/हुक/पोस्ट-लिखें।sh फ़ाइल में शामिल हैं:

# -------------------------------------------------------- 
# 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 !" 
संबंधित मुद्दे