0

I've stumbled upon git-hooks and been trying to create one to run on Windows. So I've decided upon using batch files to do so because it seemed easy enough.

First, I renamed the pre-commit sample to pre-commit and called my bat steps there:

#!/bin/sh
$(pwd)/git-hooks/hooks/unit_test.bat &&
$(pwd)/git-hooks/hooks/integration_test.bat

The unit_test.bat only shows some messages and runs the unit tests task, but the integration_test.bat prompts the user on if they want to run these tests or not because they are generally slower.

The problem is that the prompt (done with either 'choice' or 'set /p') doesn't get the user input:

  • 'set /p' doesn't wait for user input
  • 'choice' freezes and doesn't allow any user input

I've tried adding start to call the .bat files but it opens them on another cmd so it makes it impossible to stop the commit.

Files referenced

  • unit_test.bat

    @echo off
    echo ^> Testes unitários
    call gradlew testReport || (echo(& echo Testes unitários falharam! Acesse o relatório de testes para conferir.& exit 1))
    
  • integration_test.bat

    @echo off
    
    echo(echo ^> Testes integrados
    %SystemRoot%\System32\choice.exe /C sn /M "Esses testes geralmente são mais lentos. Quer rodar os testes integrados"
    if ERRORLEVEL 2 goto nao
    call gradlew integrationTests || (echo(echo Testes integrados falharam! Acesse o relatório de testes para conferir.) && exit 1)
    
    :nao
    echo(echo Não se esqueça de confirmar que os testes integrados passam antes de fazer o 'git push'!)
    exit /B
    
Álex Fogaça
  • 84
  • 1
  • 5
  • 2
    `/bin/sh` isn't the same as `/bin/bash` you are actually running a regular shell script and not a bash script because your script is calling the `/bin/sh` interpreter and not the `/bin/bash` interpreter. The path to bash may be different on your system so you might want to run `which bash` to confirm it. – Joseph Ishak Mar 10 '21 at 21:52
  • Thanks for pointing it out, I should have referenced it as shell script instead of bash then. Is this detail supposed to address the situation as well? I tried running with the ```/bin/bash``` interpreter and it doesn't seem to help – Álex Fogaça Mar 10 '21 at 21:55
  • I don't think that is the problem in your question but I try to make sure all the details as accurate as possible so that is why I mentioned. – Joseph Ishak Mar 10 '21 at 22:06
  • That's a good point and I appreciate you pointing it out. – Álex Fogaça Mar 10 '21 at 22:12
  • 1
    git hooks aren't handed a tty, if you need it you have to reopen it yourself (though interactivity during hooks is a bit of a smell imo) -- on windows I believe that's opening `CONIN$` – anthony sottile Mar 11 '21 at 15:13
  • @AnthonySottile thanks, I didn't know about the lack of interactivity on git-hooks. This was the root of the problem and now I can return to thinking about a solution to this. Thanks a lot! – Álex Fogaça Mar 11 '21 at 21:03

2 Answers2

2

I thought that gradlew was actually another batch file, gradlew.bat, so I'd assume, if you want it to return to the script upon completion you should use the Call command. Also, you should be aware that & concatenates two individual commands on one line, whereas && runs one command only when the previous one was successful. In your case, the Echo commands cannot be unsuccessful, so just & is necessary. Additionally, If ErrorLevel 1 menas if the error code was 1 or higher, which means, in your posted code, the code will always goto sim. What you should use instead is If Not ErrorLevel 2, If %ErrorLevel% Equ 1, or If "%ErrorLevel%" == "1".

Examples: (Please insert the full path to gradlew.bat instead of relying on easily corrupted or affected %Path% variable, and doublequote the path and executable name if it contains spaces or problematic characters). I have removed the unnecessary concatenation in the lower examples, as it is not required within a script.

unit_test.bat

@Echo Off
Echo ^> Testes unitários
Call gradlew.bat testReport || (Echo(& Echo Testes unitários falharam! Acesse o relatório de testes para conferir.& Exit 1)

integration_test.bat

@Echo Off
Echo(
Echo ^> Testes integrados
%SystemRoot%\System32\choice.exe /C sn /M "Esses testes geralmente são mais lentos. Quer rodar os testes integrados"
If Not ErrorLevel 2 GoTo sim
Echo(
Echo Não se esqueça de confirmar que os testes integrados passam antes de fazer o 'git push'!
Exit /B

:sim
Call gradlew.bat integrationTests || (
    Echo(
    Echo Testes integrados falharam! Acesse o relatório de testes para conferir.
)
Exit 1

or:

@Echo Off
Echo(
Echo ^> Testes integrados
%SystemRoot%\System32\choice.exe /C sn /M "Esses testes geralmente são mais lentos. Quer rodar os testes integrados"
If ErrorLevel 2 GoTo nao
Call gradlew.bat integrationTests || (
    Echo(
    Echo Testes integrados falharam! Acesse o relatório de testes para conferir.
)
Exit 1

:nao
Echo(
Echo Não se esqueça de confirmar que os testes integrados passam antes de fazer o 'git push'!
Exit /B

I would also suggest, based upon some of the characters you are using, that you ensure that the script is run using an appropriate codepage, (possibly 1252).

Compo
  • 36,585
  • 5
  • 27
  • 39
  • Thanks for correcting my mistakes and explaining them in a clear manner, it'll help to know that the error might not be because of the script syntax after these changes. I'll edit the original post. However, the freezing problem when the user has to write their choice is still happening. Maybe I've forgotten to add something meaningful that would help people reproduce it. – Álex Fogaça Mar 11 '21 at 00:54
0

The freeze error was due to the fact that git-hooks disable interactivity, as @AnthonySotille pointed out.

I bypassed that situation by extracting the prompt to another .bat file and calling them with start /wait. That opens another cmd, runs the prompt, and exits using the success code to represent Y and the failure code as N. It doesn't seem like a good practice, but for now, it does the job.

This question might be considered a duplicate of How do I prompt the user from within a commit-msg hook?

Álex Fogaça
  • 84
  • 1
  • 5