Как я могу запросить пользователя из крючка commit-msg?


Я хочу предупредить пользователя, если его сообщение о фиксации не соответствует определенному набору рекомендаций, а затем дать им возможность редактировать свое сообщение о фиксации, игнорировать предупреждение или отменить фиксацию. Проблема в том, что у меня, похоже, нет доступа к stdin.

Ниже приведен мой файл commit-msg:

function verify_info {
    if [ -z "$(grep ':.*[a-zA-Z]' )" ]
    then
        echo >&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} 
                    verify_info "" 
                    ;;
                *)  echo "CHOICE = ${CHOICE}"
                    exit 1
                    ;;
            esac
        done
    fi
}

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

exit 0

вот вывод, когда я оставляю информацию об области пустым:

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

сообщение правильное, но на самом деле оно не останавливается для ввода. У меня тоже есть пробовал использовать более простую команду "read", и у нее такая же проблема. Похоже, проблема в том, что на данный момент git контролирует stdin и предоставляет свой собственный вход. Как мне это исправить?

обновление: кажется, это может быть дубликат этот вопрос что, к сожалению, похоже, предполагает, что мне не повезло.

4 53

4 ответа:

вызов exec < /dev/tty назначает стандартный ввод на клавиатуре. Работает для меня в пост-фиксации git hook:

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

The commit-msg крюк не запускается в интерактивной среде (как вы заметили).

единственным способом надежного уведомления Пользователя было бы написать ошибку в stdout, поместить копию сообщения фиксации в BAD_MSG файл и поручить пользователю редактировать файл и git commit --file=BAD_MSG


если у вас есть некоторый контроль над средой, у вас может быть альтернативный редактор, который является сценарием-оболочкой, который проверяет предлагаемое сообщение и может перезапустить редактор с помощью дополнительное сообщение с комментариями.

в принципе, вы запускаете редактор, проверяете файл, сохраненный по вашим правилам. и если это не удается, добавьте свое предупреждающее сообщение (с ведущим #) в файл и перезапустить редактор.

вы могли бы даже позволить им поставить в #FORCE=true строка в сообщении, которая будет подавлять проверку и продолжить.

и select стоп для ввода, вы также можете попытаться перенаправить stdin на select С /dev/fd/3 (см.: чтение ввода в bash внутри цикла while).

# 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} 
             echo verify_info "" 
             ;;
         *)  echo "CHOICE = ${CHOICE}"
             exit 1
             ;;
      esac
   done 0<&3 3<&-
done
} 3<&- 3<&0

это отлично работает при запуске git commit из командной строки. В windows (не пробовал на linux) если вы используете gitk или Git-gui вы не сможете запросить, потому что вы получаете сообщение об ошибке в строке "exec

решение состоит в том, чтобы вызвать git-bash.exe в вашем крючке:

.git / hooks / post-commit содержит:

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

the .git/hooks/post-commit.sh файл содержит:

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

  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 !"