Как мне подсказать пользователю из хука commit-msg? - PullRequest
65 голосов
/ 05 августа 2010

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

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

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

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

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

Сообщение верное, но на самом деле оно не останавливается для ввода.Я также попытался использовать более простую команду «чтение», и у нее та же проблема.Кажется, что проблема в том, что в этот момент git имеет контроль над stdin и предоставляет свой собственный ввод.Как мне это исправить?

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

Ответы [ 5 ]

140 голосов
/ 04 апреля 2012

Вызов exec < /dev/tty назначает стандартный ввод для клавиатуры.У меня работает в git-крюке post-commit:

#!/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
4 голосов
/ 20 августа 2010

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

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


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

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

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

1 голос
/ 26 апреля 2017

это прекрасно работает при запуске git commit из командной строки. В windows (не пробовал в linux), если вы используете gitk или git-gui, вы не сможете получить запрос, потому что вы получаете сообщение об ошибке в строке «exec </ dev / tty». </p>

Решение состоит в том, чтобы вызвать 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

.git / hooks / post-commit.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 !"
1 голос
/ 03 мая 2013

Чтобы сделать 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} $1
             echo verify_info "$1" $2
             ;;
         *)  echo "CHOICE = ${CHOICE}"
             exit 1
             ;;
      esac
   done 0<&3 3<&-
done
} 3<&- 3<&0
0 голосов
/ 25 февраля 2019
read -p "Question? [y|n] " -n 1 -r < /dev/tty
echo
if echo $REPLY | grep -E '^[Yy]$' > /dev/null; then
#do if Yes
else
#do if No
fi
...