2016-08-31 1 views
3

Это мой крюк precommit. Когда я запускаю фиксацию, мой внешний инструмент diff появляется, но в окне cmd ничего не отображается, и он не читает ввод на клавиатуре.Крюк клиента subversion не показывает эхо

@echo off 
for /F "usebackq" %%i IN (%1) DO (svn diff %%i >nul) 
echo hello 
choice /M "Continue to commit?" 
SET userChoice=%ERRORLEVEL% 
IF %userChoice% equ 1 exit /b 0 
IF %userChoice% equ 2 exit /b 1 

My subversion configuration

ли я пропустить что-нибудь?

+2

В соответствии с [справочной документации TortoiseSVN] (https: //tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-dug-settings.html#tsvn-dug-settings-hooks) вам нужно выполнить ** явное перенаправление на консоль (устройство 'con') **, например' echo Проверка состояния> con' или 'pause < con > con' ... – aschipfl

+0

@aschipfl' choice/M "Продолжить фиксацию?«< con > con' дает ошибку: ОШИБКА: дескриптор недействителен. – Gqqnbig

+0

Я никогда не делал этого с помощью команды' choice', я использовал только '> con echo' и' pause < con > con' для отладки, которая работает, вы также можете попробуйте использовать '< con > con set/P' ... – aschipfl

ответ

3

Согласно help documentation of TortoiseSVN вам нужно сделать явное перенаправление на консоль (устройство con):

When debugging hook scripts you may want to echo progress lines to the DOS console, or insert a pause to stop the console window disappearing when the script completes. Because I/O is redirected this will not normally work. However you can redirect input and output explicitly to CON to overcome this. e.g.

echo Checking Status > con 
pause <con> con 

К сожалению, это не работает с командой choice, как это, кажется, не принимает перенаправления ввода с устройства con:

>>> choice < con 
ERROR: The handle is invalid. 

простой обходной использовать set /P команда, которая поддерживает перенаправление из con:

@echo off 
setlocal EnableExtensions DisableDelayedExpansion 

rem // Loop structure for prompting user: 
:CONFIRM 
rem // Display prompt and await user input: 
<con> con set /P SELECT="Continue? [Yes/No]?" 
rem // Check user input case-insensitively: 
if /I "%SELECT%"=="Y" exit /B 0 
if /I "%SELECT%"=="Yes" exit /B 0 
if /I "%SELECT%"=="N" exit /B 1 
if /I "%SELECT%"=="No" exit /B 1 
rem // Repeat prompt in case of invalid entry: 
goto :CONFIRM 

endlocal 
exit /B 

Недостатком этого является то, что запись должна быть прекращена с RETURN, в отличие от choice команды, которая принимает один ключ ввода.


Вот лучший подход, который показывает один ключ приглашение аналогично команде choice. Это (неверно) использует команду xcopy и ее способность принимать перенаправленный ввод в запросе подтверждения копирования, которое появляется, когда поставляется переключатель /W. Также обратите внимание на пояснительные замечания:

@echo off 
setlocal EnableExtensions EnableDelayedExpansion 

rem // Loop structure for prompting user: 
:CONFIRM 
rem // Display prompt without trailing line-break: 
<nul> con set /P ="Continue? [Y/N]?" 
rem /* Let `xcopy` wait for a single-key entry using its `/W` switch; 
rem `/L` tells `xcopy` to actually copy nothing; to avoid problems 
rem with inexistent paths, use this script's path as source file 
rem and the system's temporary directory as the target location: */ 
< con (
    for /F "delims=" %%L in (' 
     xcopy /L /W "%~f0" "%TMP%\" 
    ') do (
     rem /* Capture the copy confirmation prompt of `xcopy /L /W`, 
     rem `Press any key when ready to begin copying file(s)`, 
     rem together with the character entered by the user, which 
     rem is appended to the prompt message: */ 
     set "CHAR=%%L" 
     rem /* Leave loop upon first iteration, because we are not 
     rem interested in any copying results and summaries: */ 
     goto :SKIP 
    ) 
) 
:SKIP 
rem // Extract the last character, which is the actual user input: 
set "CHAR=!CHAR:~-1!" 
rem // Display user entry: 
> con echo(!CHAR! 
rem // Check user input case-insensitively: 
if /I "!CHAR!"=="Y" exit /B 0 
if /I "!CHAR!"=="N" exit /B 1 
rem // Repeat prompt in case of invalid entry: 
goto :CONFIRM 

endlocal 
exit /B 

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


Чтобы избежать повторной печати текста подсказки в случае неожиданного пользовательского ввода, используйте следующий скрипт:

@echo off 
setlocal EnableExtensions DisableDelayedExpansion 

rem // Define constants here: 
set "MESSAGE=Confirm? [Y/N]?" 

rem // Retrieve back-space character: 
for /F %%Z in ('prompt $H ^& for %%Z in ^(.^) do rem/') do set "BS=%%Z" 
rem // Retrieve carriage-return character: 
for /F %%Z in ('copy /Z "%~f0" nul') do set "CR=%%Z" 

rem // Loop structure for prompting user: 
:CONFIRM 
setlocal EnableDelayedExpansion 
rem // Display prompt without trailing line-break: 
> con < nul set /P ="%BS% !CR!!MESSAGE!" 
endlocal 
rem /* Let `xcopy` wait for a single-key entry using its `/W` switch; 
rem `/L` tells `xcopy` to actually copy nothing; to avoid problems 
rem with inexistent paths, use this script's path as source file 
rem and the system's temporary directory as the target location: */ 
< con (
    for /F "delims=" %%L in (' 
     xcopy /L /W "%~f0" "%TMP%\" 
    ') do (
     rem /* Capture the copy confirmation prompt of `xcopy /L /W`, 
     rem `Press any key when ready to begin copying file(s)`, 
     rem together with the character entered by the user, which 
     rem is appended to the prompt message: */ 
     set "CHAR=%%L" 
     rem /* Leave loop upon first iteration, because we are not 
     rem interested in any copying results and summaries: */ 
     goto :SKIP 
    ) 
) 
:SKIP 
setlocal EnableDelayedExpansion 
rem // Extract the last character, which is the actual user input: 
set "CHAR=!CHAR:~-1!" 
rem // Display user entry without trailing line-break: 
> con < nul set /P ="!CHAR!" 
rem // Check user input case-insensitively: 
if /I "!CHAR!"=="Y" exit /B 0 
if /I "!CHAR!"=="N" exit /B 1 
endlocal 
rem // Repeat prompt in case of invalid entry: 
goto :CONFIRM 
echo/ 

endlocal 
exit /B 

Это комплексное решение, которое позволяет использовать специальные символы, как !, ^ и " тоже ,


Вот вполне аналогичное решение, опираясь на команде replace, вместе с его /W выключателем, а также без перепечатки подсказки в случае неожиданного пользовательского ввода. Поскольку replace печатает характер нажатия клавиши в отдельной строке, нет никакой необходимости, чтобы разделить его на другую строку (в отличие от xcopy /W):

@echo off 
setlocal EnableExtensions DisableDelayedExpansion 

rem // Define constants here: 
set "MESSAGE=Confirm? [Y/N]?" 

rem // Retrieve back-space character: 
for /F %%Z in ('prompt $H ^& for %%Z in ^(.^) do rem/') do set "BS=%%Z" 
rem // Retrieve carriage-return character: 
for /F %%Z in ('copy /Z "%~f0" nul') do set "CR=%%Z" 

rem // Loop structure for prompting user: 
:CONFIRM 
setlocal EnableDelayedExpansion 
rem // Display prompt without trailing line-break: 
> con < nul set /P ="%BS% !CR!!MESSAGE!" 
endlocal 
rem /* Let `replace` wait for a single-key entry using its `/W` switch; 
rem `/U` tells `replace` to actually do nothing; to avoid problems 
rem with inexistent paths, use this script's path as source file 
rem and its parent directory as the target location: */ 
< con (
    for /F "skip=1 delims=" %%L in (' 
     replace /W /U "%~f0" "." 
    ') do (
     rem /* Capture the confirmation user input of `replace /W /U`, 
     rem skipping the prompt `Press any key to continue . . .`: */ 
     set "CHAR=%%L" 
     rem /* Leave loop upon first iteration, because we are not 
     rem interested in any replacement results and summaries: */ 
     goto :SKIP 
    ) 
) 
:SKIP 
setlocal EnableDelayedExpansion 
rem // Display user entry without trailing line-break: 
> con < nul set /P ="!CHAR!" 
rem // Check user input case-insensitively: 
if /I "!CHAR!"=="Y" exit /B 0 
if /I "!CHAR!"=="N" exit /B 1 
endlocal 
rem // Repeat prompt in case of invalid entry: 
goto :CONFIRM 
echo/ 

endlocal 
exit /B 
+0

большое вам спасибо! настолько сложной и неоднородной. – Gqqnbig

Смежные вопросы