Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I prompt the user from within a commit-msg hook?

I want to warn the user if their commit message doesn't follow a certain set of guidelines, and then give them the option to edit their commit message, ignore the warning, or cancel the commit. The problem is that I don't seem to have access to stdin.

Below is my commit-msg file:

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 

Here is the output when I leave the Scope information blank:

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

The message is correct, but it doesn't actually stop for input. I've also tried using the simpler "read" command, and it has the same problem. It seems that the problem is that at this point git has control of stdin and is providing its own input. How do I fix this?

Update: It seems this might be a duplicate of this question which unfortunately seems to suggest I'm out of luck.

like image 688
Ben Hocking Avatar asked Aug 05 '10 18:08

Ben Hocking


People also ask

How do you trigger a pre-commit hook?

If you want to manually run all pre-commit hooks on a repository, run pre-commit run --all-files . To run individual hooks use pre-commit run <hook_id> . The first time pre-commit runs on a file it will automatically download, install, and run the hook. Note that running a hook for the first time may be slow.

What is a commit-msg hook?

The commit-msg hook is much like the prepare-commit-msg hook, but it's called after the user enters a commit message. This is an appropriate place to warn developers that their message doesn't adhere to your team's standards. The only argument passed to this hook is the name of the file that contains the message.


2 Answers

Calling exec < /dev/tty assigns standard input to the keyboard. Works for me in a post-commit 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 
like image 50
Eliot Sykes Avatar answered Sep 18 '22 20:09

Eliot Sykes


The commit-msg hook is not run in an interactive environment (as you have noticed).

The only way to reliable notify the user would be to write an error to stdout, place a copy of the commit message in a BAD_MSG file and instruct the user to edit the file and git commit --file=BAD_MSG


If you have some control over the environment you could have an alternate editor which is a wrapper script that checks the proposed message, and can restart the editor with an extra commented message.

Basically, you run the editor, check the file saved against your rules. and if it fails, prepend your warning message (with leading #) to the file and restart the editor.

You could even allow them to put in a #FORCE=true line in the message which would suppress the check and continue.

like image 31
Frosty Avatar answered Sep 18 '22 20:09

Frosty