Как я могу запросить пользователя из крючка 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 ответа:
вызов
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 !"